SpringBoot知识点及其源码解析(1)

自动配置

以web启动器为例,在spring-boot-starter-test-3.4.3.pom文件整合了一系列的依赖,那么当启动程序后会不会进行自动配置?当获取到这个容器后,可以从容器中获取所有bean的名字,此时就可以在控制台发现很多bean的名称,都是自动配置进来的。

@SpringBootApplication
public class Demo1Application {

    public static void main(String[] args) {
        // 初始化IOC容器
        ConfigurableApplicationContext configurableApplicationContext = SpringApplication.run(Demo1Application.class, args);
        // 从容器中获取所有的bean的名字
        String[] beanDefinitionNames = configurableApplicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }

}

在这里,也可以发现自定义的bean,这是由于@RestController这个注解,等价于@Controller+@ResponseBody,它标记类为REST控制器,即标识一个类为SpringMVC控制器,处理HTTP请求,与传统的@Controller相比,直接返回数据,不返回视图。要使用注解管理类的化,前提要开启包扫描,在启动类的@SpringBootApplication注解下有@ComponentScan,这个注解行包扫描,规则是扫描当前的类(Demo1Application)的目录(demo1)及其子目录(controller)

  • 如果定义了某一个场景的启动器,那么项目在加载的时候,会开启对这个启动器的自动配置,会将这个启动器所属依赖里面的相关组件全部交给ioc容器进行管理。
  • 自定义组件,通过@ComponentScan注解进行包扫描,规则是扫描当前的类的目录及其子目录。
  • springboot不会将所有场景的资源进行自动配置,采取的是按需加载的方式进行自动配置,只有导入对应场景的启动器,那么相关组件才能被管理到ioc容器中

注解

@Configuration

管理bean的方式

  • xml的方式管理bean
  • 使用注解方式管理bean,@Component,@Controller,@Service,@Repository
  • 配置类

        @Configuration标识当前的类是一个配置类,类似于spring里的xml配置文件,@Bean像ioc容器添加组件,类似于xml文件中的bean标签,返回值类型是添加到容器组件的数据类型,可以在启动类进行ioc容器中获取bean之后打印,即可得到注入的类。

        被@Configuration修饰的配置类,也被交给容器进行管理,由于内部集成了@Conponent注解

MyConfig myConfig = context.getBean(MyConfig.class);
System.out.println(myConfig);
com.example.demo2.config.MyConfig$$SpringCGLIB$$0@7316523a

其中的SpringCGLIB表示这个配置类所属的bean是一个基于CGLIB字节码增强的代理对象

        在@Configuration注解内部有一个boolean proxyBeanMethods() default true;表示每个@Bean方法被调用返回的组件都是单例的,如果变为false的话,每个@Bean方法被调用的组件都是新创建的。

@Import

  • 在配置类上加入@Import(value={Animal.class})后在启动类获取bean的名称,得到com.example.demo2,pojo.Animal表示向容器中导入一个普通类的组件,组件名称是Animal的全限定名。
  • 也可以导入配置配置类,名称是配置类的名称
  • 导入ImportSelector接口实现的类
  • 导入ImportBeanDefinitionRegistrar接口实现的类
  • 总之,可以通过@Import注解向容器中导入一个组件

@Conditional

根据条件动态控制 Bean 的注册或配置类的解析。其核心作用是通过条件判断决定目标对象(如 Bean 或配置类)是否被 Spring 容器处理。SpringBoot在@ConditionalOnBean注解的集成上实现了细化,无需实现Condition接口,只需使用定义好的@ConditionalOnXXX注解,就会注入到IOC容器。例如@ConditionalOnBean(name = "cat"),表示容器中存在cat这个bean,当前@Bean注解修饰的组件才会被装配到容器中;@ConditionalOnMissBean(name = "cat"),表示容器中不存在cat这个bean,当前@Bean注解修饰的组件才会被装配到容器中。

@ImportResource

springboot 默认是不识别 xml 配置文件的,如果我们实在想在 springboot 项目中使用 xml 配置文件,需 要使用 @ImportResource 注解导入 xml 配置文件

配置绑定注解

在原生的spring中可以通过set方法或者构造方法进行注入,也可以基于注解的方式进行注入。

Set方法注入
<bean id="userService" class="com.example.UserServiceImpl">
    <property name="userDao" ref="userDao"/>
</bean>
public class UserServiceImpl {
    private UserDao userDao;
    
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
}

构造方法注入
<bean id="userService" class="com.example.UserServiceImpl">
    <constructor-arg ref="userDao"/>
</bean>
public class UserServiceImpl {
    private final UserDao userDao;
    
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }
}

基于注解的注入
public class UserServiceImpl {
    @Autowired
    private UserDao userDao;
}

那么在springboot中如何进行配置属性的自动绑定

  • @Value 注解手动进行绑定:@Value("${car.name}") private String name;

  • @Component+@ConfigurationProperties注解进行属性的自动绑定:@ConfigurationProperties(prefix="car") public class car {}

  • @Configuration+@EnableConfigurationProperties注解进行属性的自动绑定:在配置类上进行定义

依赖注入和自动绑定

自动绑定(通过@ConfigurationProperties注解实现功能)时将外部的配置(如application.yml)的属性自动映射到Java对象中,目的是简化配置管理。依赖注入时管理对象之间的依赖关系,由Spring容器负责创建对象并注入其所需的依赖,目的是为了减少代码之间的耦合度。

工作流程:启动类加载(@SpringBootApplication)-->  自动扫描文件下的自动配置类(AutoConfigurationImportSelector)--> 自动配置(SpringBoot检查条件注解,例如@ConditionalOnClass,满足条件才会实例化相应的bean并注入到ioc容器中)-->配置属性的绑定(@ConfigurationProperties进行标注配置属性) --> 依赖注入(构造器,setter方法或者注解)-->环境准备-->启动程序

springboot自动配置原理

包扫描规则原理

从前面可知,扫描的目录是启动器所在的目录及其子目录。

自动配置类的加载 

// annotationMetadata 中获取于@EnableAutoConfiguration相关的属性
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);  
// 获取所有候选的自动配置类的全限定名列表(只关注这个)
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
// 去除重复的配置类名称,避免重复加载
configurations = this.removeDuplicates(configurations);
// 获取注解中明确排除的那些自动配置类
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
// 验证排除的类是否确实存在于候选配置类列表中
this.checkExcludedClasses(configurations, exclusions);
// 将用户指定要排除的自动配置类从候选列表中移除
configurations.removeAll(exclusions);
// 过滤器进一步筛选配置类,可能是基于环境、条件注解等
configurations = this.getConfigurationClassFilter().filter(configurations);
// 通知关于即将导入的自动配置类和被排除的类的信息
this.fireAutoConfigurationImportEvents(configurations, exclusions);
// 包含了经过上述处理后的最终自动配置类列表以及被排除的类集合
return new AutoConfigurationEntry(configurations, exclusions);

其中的ImportCandidates.load(this.autoConfigurationAnnotation, this.getBeanClassLoader());是用以加载自动配置类的关键步骤,使用了ImportCandidates类来从classpath中读取指定的自动配置类列表。

  • this.autoConfigurationAnnotation: 这是一个指向@EnableAutoConfiguration注解的引用。在Spring Boot的上下文中,表示寻找与自动配置相关的类。

  • this.getBeanClassLoader(): 这个方法返回的是当前应用上下文使用的类加载器。类加载器是Java虚拟机用来查找和加载类的关键组件。在这里,它被用来定位classpath上的资源文件。

  • ImportCandidates.load(...): 这个静态方法会根据传入的注解(这里是@EnableAutoConfiguration)和类加载器来查找并读取相应的AutoConfiguration.imports文件。然后,它会解析该文件中的每一行作为全限定类名,并将这些类名收集到一个列表中返回

  • String location = String.format("META-INF/spring/%s.imports", annotation.getName());表示的就是路径

打个断点,就能得到name,因此总路径是INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

 由断言和上面的总路径可知进入D:\java\mvn_repository\org\springframework\boot\spring-boot-autoconfigure\3.4.3\spring-boot-autoconfigure-3.4.3.jar!\META-INF\spring\org.springframework.boot.autoconfigure.AutoConfiguration.imports这里,就可以看到很多配置信息,

那么可以得出,当加载配置信息的时候,就是加载的这153项,下图的debug也可以证明

总结

自动配置类加载流程 

AOP

AOP是如何进行自动配置的,在D:\java\mvn_repository\org\springframework\boot\spring-boot-autoconfigure\3.4.3\spring-boot-autoconfigure-3.4.3.jar!\org\springframework\boot\autoconfigure\aop\AopAutoConfiguration.class路径下,有一个注解

@ConditionalOnProperty(
    prefix = "spring.aop",
    name = {"auto"},
    havingValue = "true",
    matchIfMissing = true
)

注解要生效,必须存在spring.aop开头的配置信息,在这个配置信息下,必须有一个auto属性,而且必须为true,在配置文件中的默认值为true,那么此时进行了自动的配置,下面进行验证

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(App.class, args);
        String[] names = context.getBeanNamesForType(AopAutoConfiguration.class);
        System.out.println(names.length);
        for (String s : names) {
            System.out.println(s);
        }
    }
}

 在AopAutoConfiguration.class类下,有一个AspectJAutoProxyingConfiguration类,被@ConditionalOnClass({Advice.class})进行修饰,表示如果没有导入Advice.class这个类,表示这个注入不生效,Advice.class在import org.aspectj.weaver.Advice;包下,但是现在并不存在这个包,就是没有在pom.xml引入相关的依赖,那么AspectJAutoProxyingConfiguration类在容器中也是不存在的。代码进行验证报错,即组件没有教给容器管理

cache

导入CatchAutoConfiguration之前要做很多条件注入

DispatcherServletAutoConfiguration

在package org.springframework.boot.autoconfigure.web.servlet;下

 

 

总结 

  1. 自动配置类的名称xxxAutoConfiguration
  2. 自动配置类会开启信息的自动绑定,都会将定义的自动配置信息绑定到一个xxxProperties上面
  3. 自动配置类里面会通过@Bean注解 装配很多组件到ioc容器里面去(有很多条件装配)
  4. springboot永远以用户配置的组件为准,如果用户没有配置,就以springboot默认配置的为准
    @ConditionalOnMissingBean
  5. springboot很多配置信息都设置了默认值,如果用户修改,就以默认值为准,如果用户修改了,就以用户设置的值为准,例如:server.port

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/983194.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络安全配置截图 网络安全i

网络安全概念及规范 1.网络安全定义 网络安全的概述和发展历史 网络安全 广义的网络安全&#xff1a;Cyber Security&#xff08;网络空间安全&#xff09; 网络空间有独立且相互依存的信息基础设施和网络组成&#xff0c;包括互联网、电信网、计算机系统、嵌入式处理器和控…

【ThreeJS Basics 09】Debug

文章目录 简介从 dat.GUI 到 lil-gui例子安装 lil-gui 并实例化不同类型的调整改变位置针对非属性的调整复选框颜色 功能/按钮调整几何形状文件夹调整 GUI宽度标题关闭文件夹隐藏按键切换 结论 简介 每一个创意项目的一个基本方面是能够轻松调整。开发人员和参与项目的其他参与…

第六课:数据存储三剑客:CSV/JSON/MySQL

在Python的数据存储与处理领域&#xff0c;CSV、JSON和MySQL被广大开发者誉为“数据存储三剑客”。它们各自在不同的场景下发挥着重要作用&#xff0c;无论是简单的数据交换、轻量级的数据存储&#xff0c;还是复杂的关系型数据库管理&#xff0c;都能找到它们的身影。本文将详…

CSS设置文字渐变色样式(附带动画效果)

最近用DeepSeek问了一下如何使用css设置文字的渐变色效果&#xff0c;并且希望可以有动画效果&#xff0c;然而DeepSeek给出的答案动画效果有些bug&#xff0c;于是自己动手改了改。 下面是CSS样式设置代码 .gradient-text {background-image: linear-gradient(to right, #ff6…

三维建模与视频融合(3D-Video Integration)技术初探。

三维建模与视频融合&#xff08;3D-Video Integration&#xff09;是一种将虚拟三维模型无缝嵌入实拍视频场景的技术&#xff0c;广泛应用于影视特效、增强现实&#xff08;AR&#xff09;、游戏开发、广告制作 、视频监控 等领域。 一、技术核心流程 三维建模与动画 使用工具…

electron + vue3 + vite 主进程到渲染进程的单向通信

用示例讲解下主进程到渲染进程的单向通信 初始版本项目结构可参考项目&#xff1a;https://github.com/ylpxzx/electron-forge-project/tree/init_project 主进程到渲染进程&#xff08;单向&#xff09; 以Electron官方文档给出的”主进程主动触发动作&#xff0c;发送内容给渲…

第八节:基于Winform框架的串口助手小项目---完结优化《C#编程》

C# 实战串口助手完成&#xff01; ----------------------------不竭余力&#xff0c;方能成长&#xff01;-----------WHAPPY 源码&#xff1a;我会分享开源平台&#xff0c;可以艾特me&#xff01;&#xff08;2025/3/5&#xff09;时间紧张任务中&#xff01; 文章上所说的…

SpringBoot接入DeepSeek(硅基流动版)+ 前端页面调试(WebSocket连接模式)

文章目录 前言正文一、项目环境二、项目代码2.1 pom.xml2.2 DeepSeekController.java2.3 启动类2.4 logback-spring.xml2.5 application.yaml2.6 WebsocketConfig.java2.7 AiChatWebSocketHandler.java2.8 SaveChatSessionParamRequest.java2.9 index.html 三、页面调试3.1 主页…

计算机视觉之dlib人脸关键点绘制及微笑测试

dlib人脸关键点绘制及微笑测试 目录 dlib人脸关键点绘制及微笑测试1 dlib人脸关键点1.1 dlib1.2 人脸关键点检测1.3 检测模型1.4 凸包1.5 笑容检测1.6 函数 2 人脸检测代码2.1 关键点绘制2.2 关键点连线2.3 微笑检测 1 dlib人脸关键点 1.1 dlib dlib 是一个强大的机器学习库&a…

进程控制 ─── linux第15课

目录 进程控制 1.进程创建 fork函数 写时拷贝 fork常规用法 fork调用失败的原因 进程终止 进程退出的场景 退出码 ​编辑 进程终止的方法 _exit函数 exit函数 exit与_exit 进程等待 进程等待必要性 进程等待的方法(wait 和waitpid) 阻塞非阻塞问题 ​编辑 非…

Kubernetes 的正式安装

1.基础的网络结构说明 软件路由器 ikuai 当然同一个仅主机模式 相当于在 同一个我们所谓的广播域内 所以相当于它们的几张网卡 是被连接起来的 为了防止出现问题 我们可以把第二块网卡临时关闭一下 2.准备路由器 ikuai 爱快 iKuai-商业场景网络解决方案提供商 (ikuai8.com)…

【为什么会有 map、weakmap 类型?】

为什么会有 map、weakmap 类型? 传统对象的局限性催生 Map‌1. 键类型单一性‌2. 有序性与迭代支持‌3. 性能优化场景‌ 内存管理需求催生 WeakMap‌1.弱引用机制‌2. 私有数据存储‌3. 规避循环引用问题‌ 总结 传统对象的局限性催生 Map‌ 1. 键类型单一性‌ 传统对象&…

HTML-05NPM使用踩坑

2025-03-04-NPM使用踩坑 本文讲述了一个苦逼程序员在使用NPM的时候突然来了一记nmp login天雷&#xff0c;然后一番折腾之后&#xff0c;终究还是没有解决npm的问题&#x1f61e;&#x1f61e;&#x1f61e;,最终使用cnpm完美解决的故事。 文章目录 2025-03-04-NPM使用踩坑[toc…

java后端开发day27--常用API(二)正则表达式爬虫

&#xff08;以下内容全部来自上述课程&#xff09; 1.正则表达式&#xff08;regex&#xff09; 可以校验字符串是否满足一定的规则&#xff0c;并用来校验数据格式的合法性。 1.作用 校验字符串是否满足规则在一段文本中查找满足要求的内容 2.内容定义 ps&#xff1a;一…

鸿蒙HarmonyOS评论功能小demo

评论页面小demo 效果展示 1.拆解组件&#xff0c;分层搭建 我们将整个评论页面拆解为三个组件&#xff0c;分别是头部导航&#xff0c;评论项&#xff0c;回复三个部分&#xff0c;然后统一在index界面导入 2.头部导航界面搭建 Preview Component struct HmNavBar {// 属性&a…

智能机器人学习机WT3000A AI芯片方案-自然语音交互 打造沉浸式学习体验

一、概述 当AI浪潮席卷全球&#xff0c;教育领域也未能幸免。AI学习机&#xff0c;这个打着“个性化学习”、“精准提分”旗号的新兴产品&#xff0c;正以惊人的速度占领市场。从一线城市到偏远乡镇&#xff0c;从学龄前儿童到高考备考生&#xff0c;AI学习机的广告铺天盖地&am…

鸿蒙与DeepSeek深度整合:构建下一代智能操作系统生态

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/north 目录 技术融合背景与价值鸿蒙分布式架构解析DeepSeek技术体系剖析核心整合架构设计智能调度系统实现…

【UCB CS 61B SP24】Lecture 22 23: Tree and Graph Traversals, DFS, BFS 学习笔记

本文讲解了二叉树的四种遍历方式&#xff0c;以及如何通过前/后序遍历与中序遍历重建出二叉树&#xff0c;接着介绍了新的非线性数据结构&#xff1a;图&#xff0c;详细讲解了图的存储方式与遍历方式&#xff0c;最后使用 Java 基于邻接表的存储方式实现了图与 DFS、BFS 两种遍…

GCC RISCV 后端 -- C语言语法分析过程

在 GCC 编译一个 C 源代码时&#xff0c;先会通过宏处理&#xff0c;形成 一个叫转译单元&#xff08;translation_unit&#xff09;&#xff0c;接着进行语法分析&#xff0c;C 的语法分析入口是 static void c_parser_translation_unit(c_parser *parser); 接着就通过类似递…

Swagger-01.介绍和使用方式

一.Swagger介绍 有了接口文档&#xff0c;我们就可以根据接口文档来开发后端的代码了。如果我们开发完了某个功能&#xff0c;后端如何验证我们开发的是否正确呢&#xff1f;我们就需要测试&#xff0c;使用Swagger就可以帮助后端生成接口文档&#xff0c;并且可以进行后端的接…