Spring Boot源码(三)Spring Boot核心启动类、自动配置原理剖析
一、抛出问题
在学习Spring Boot自动配置原理前,我们先思考以下问题:
- 1、什么是自动配置?
- 2、自动配置是如何实现的?都把哪些组件进行了自动配置呢?
这两个问题我们可能需要针对最核心的一些注解源码的解读,才能找到答案,那就开始记录我的学习过程吧~
由于源码内容很多,就不直接贴代码了,源码部分我做了详细的注释,有需要的小伙伴可以关注我私信获取,共勉!😉😃
二、什么是自动配置?
自动配置:根据我们添加的jar包依赖,会自动将一些配置类的bean注册进ioc容器,我们可以在需要的地方使用@autowired或者@resource等注解来使用它。
三、源码中常用类及功能速查
由于阅读源码时有很多Spring相关的注解和内容,所以这里先简单列一个清单,以便在下面分析自动配置原理时可以速查:
- DeferredImportSelector【后置装载器】:等所有的@Bean,@Configuration都装载完毕后才会进行装载。
- AutoConfigurationImportSelector【自动配置装载器】:自动配置的核心,负责选择一些符合条件的自动配置类,后续让Spring容器去装载。
- ConfigurationClassParser【配置类解析器】:用于分析@Configuration注解的配置类,并递归分析配置类的注解@Import。
四、@SpringBootApplication注解解析
SpringBoot应用的启动入口:@SpringBootApplication注解标注类中的main()方法。
@SpringBootApplication:标注在某个类上说明这个类是SpringBoot的主配置/启动类,SpringBoot应用启动时就会运行该类的main()方法。
/*========== 元注解部分【有梦想的肥宅】 ==========*/ @Target(ElementType.TYPE) //注解的适用范围,Type表示注解可以描述在类、接口、注解或枚举中。 @Retention(RetentionPolicy.RUNTIME) //表示注解的生命周期,Runtime运行时 @Documented //表示注解可以记录在javadoc中 @Inherited //表示可以被子类继承该注解 /*========== SpringBoot核心三大注解【有梦想的肥宅】 ==========*/ @SpringBootConfiguration //标明该类为配置类【内部核心其实就是@Configuration】 @EnableAutoConfiguration //启动自动配置功能 @ComponentScan(excludeFilters = {@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)}) public @interface SpringBootApplication { /* 这里利用了@AliasFor的其中一个功能:整合其他注解的属性【有梦想的肥宅】*/ // 根据class来排除特定的类,使其不能加入spring容器,传入参数value类型是class类型。 @AliasFor(annotation = EnableAutoConfiguration.class) Class<?>[] exclude() default {}; // 根据classname来排除特定的类,使其不能加入spring容器,传入参数value类型是class的全类名字符串数组。 @AliasFor(annotation = EnableAutoConfiguration.class) String[] excludeName() default {}; // 指定扫描包,参数是包名的字符串数组。 @AliasFor(annotation = ComponentScan.class, attribute = "basePackages") String[] scanBasePackages() default {}; // 扫描特定的包,参数类似是Class类型数组。 @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses") Class<?>[] scanBasePackageClasses() default {}; // 整合了Configuration中的proxyBeanMethods属性:控制Bean是否使用代理,默认为ture,效果为每次取对象都是取出同一个被IOC代理的对象【单例】 @AliasFor(annotation = Configuration.class) boolean proxyBeanMethods() default true; }
PS:@SpringBootApplication注解其实可以由以下3个注解来替换:
- @SpringBootApplication
- @EnableAutoConfiguration
- @ComponentScan
@SpringBootConfiguration【标识核心配置类】
PS:@SpringBootConfiguration注解的作用与@Configuration注解相同,都是标识一个可以被组件扫描器扫描的配置类,只不过@SpringBootConfiguration是被Spring Boot进行了重新封装命名而已。
@EnableAutoConfiguration【自动配置的核心】
Spring中有很多以Enable开头的注解,其作用就是借助@Import来收集并注册特定场景相关的Bean,并加载到IOC容器。
@EnableAutoConfiguration就是借助@Import来收集所有符合自动配置条件的bean定义,并加载到IOC容器。
@AutoConfigurationPackage【自动配置包】
AutoConfigurationPackages.Registrar主要功能:注册一个Bean【AutoConfigurationPackages.BasePackages这个内部类】
@Import(AutoConfigurationImportSelector.class)【导入组件】
自动配置实现逻辑的入口方法
ConfigurationClassParser.DeferredImportSelectorGrouping.getImports()
代码分析
/** * 获取需要【后置装载】的Bean * @return */ public Iterable<DeferredImportSelector.Group.Entry> getImports() { //1、获得ConfigurationClassParser.DeferredImportSelectorHolder类型的迭代器
//PS:这里DeferredImportSelector主要功能是:【解析完成所有@Bean,@compoent等注解以后才会开始导入我们的@import内容】 //deferredImports = List<ConfigurationClassParser.DeferredImportSelectorHolder> Iterator var1 = this.deferredImports.iterator(); //2、遍历【deferredImports集合内部装各种ImportSelector】 while(var1.hasNext()) { //2.1 利用DeferredImportSelector.Group的process方法来处理自动配置的相关逻辑,决定导入哪些配置类(这个是我们分析的重点,自动配置的逻辑全在这了) ConfigurationClassParser.DeferredImportSelectorHolder deferredImport = (ConfigurationClassParser.DeferredImportSelectorHolder)var1.next(); //参数1:元数据信息 //参数2:AutoConfigurationImportSelector //PS:这里需要进入AutoConfigurationImportSelector来查看实现的process()方法 this.group.process(deferredImport.getConfigurationClass().getMetadata(), deferredImport.getImportSelector()); } //2.2 经过上面的处理后,然后再进行选择导入哪些配置类 return this.group.selectImports(); }
Q:看到这里肯定有点懵圈,为什么@Import(AutoConfigurationImportSelector.class)要去看ConfigurationClassParser这个类呢?
A:这是因为ConfigurationClassParser主要用于分析@Configuration注解的配置类,并递归分析配置类的注解@Import。而我们前面分析的@SpringBootApplication注解正好也是一个配置类,那么递归分析@import时,就会很自然的导入AutoConfigurationImportSelector类,所以我们下面需要重点分析的就是AutoConfigurationImportSelector这个类了。
AutoConfigurationImportSelector.class【自动配置核心方法在这个类内部实现,重点来了啊!!!!!】
PS:至此AutoConfigurationImportSelector.process()方法最核心的部分就分析完了,其最主要的功能就是构建出AutoConfigurationEntry来获取符合条件的自动配置类,并筛选过滤不必要的自动配置类防止其造成内存浪费。
AutoConfigurationImportSelector.process()主要工作小结:
- 1、从spring.factories配置文件中加载EnableAutoConfiguration自动配置类。
- 2、若@EnableAutoConfiguration等注解标有要exclude的自动配置类,则将这个自动配置类排除掉。
- 3、排除掉要exclude的自动配置类后,再调用filter方法进行进一步的过滤,再次排除一些不符合条件的自动配置类。
- 4、经过重重过滤后,此时再触发AutoConfigurationImportEvent事件,告诉ConditionEvaluationReport条件评估报告器对象来记录符合条件的自动配置类。
- 5、 最后将符合条件的自动配置类返回。
@ComponentScan注解【包扫描】
主要作用:从定义的扫描路径中,找出标识了需要装配的类,并自动装配到spring的IOC容器中。
常用属性:
- basePackages、value:指定扫描路径,如果为空则以@ComponentScan注解的类所在的包为基本的扫描路径
- basePackageClasses:指定具体扫描的类
- includeFilters:指定满足Filter条件的类
- excludeFilters:指定排除Filter条件的类
五、小结
到这里核心启动类就分析得差不多了,短短的篇章其实内部有很多源码还是需要自己下载以后慢慢打断点来理解的,这篇文章先作为记录核心启动类的内部究竟做了啥工作,在后面的文章我会结合案例和画图的形式去更形象地分析Spring Boot的源码,希望能帮到饱受源码困扰的小伙伴呀~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律