SpringBoot⾃动配置注解源码解析
前⾔
为什么Spring Boot这么⽕?因为便捷,开箱即⽤,但是你思考过为什么会这么便捷吗?传统的SSM架构配置⽂件⾄少要写半天,⽽使⽤Spring Boot之后只需要引⼊⼀个starter之后就能直接使⽤,why
原因很简单,每个starter内部做了⼯作,⽐如Mybatis的启动器默认内置了可⽤的SqlSessionFactory。
⾄于如何内置的?Spring Boot⼜是如何使其⽣效的?这篇⽂章就从源码⾓度介绍⼀下Spring Boot的⾃动配置原理。
源码版本
作者Spring Boot是基于2.4.0。每个版本有些变化,读者尽量和我保持⼀致,以防源码有些出⼊。
@SpringBootApplication⼲了什么?
这么说吧,这个注解什么也没做,废物,活都交给属下做了,源码如下:
上⽅标注了三个重要的注解,如下:
1. @SpringBootConfiguration:其实就是@Configuration,因此主启动类可以当做配置类使⽤,⽐如注⼊Bean等。
2. @EnableAutoConfiguration:这个注解⽜批了,名字就不⼀样,开启⾃动配置,哦,关键都在这了.....
3. @ComponentScan:包扫描注解。
经过以上的分析,最终定位了⼀个注解@EnableAutoConfiguration,顾名思义,肯定和⾃动配置有关,要重点分析下。
@EnableAutoConfiguration⼲了什么?
想要知道做了什么肯定需要看源码,如下:
上⽅标注了两个重要的注解,如下:
1. @AutoConfigurationPackage:⾃动配置包注解,默认将主配置类(@SpringBootApplication)所在的包及其⼦包⾥⾯的所有组件扫描到IOC容
器中。
2. @Import:该注解不必多说了,前⾯⽂章说过很多次了,这⾥是导⼊了AutoConfigurationImportSelector,⽤来注⼊⾃动配置类。
以上只是简单的分析了两个注解,下⾯将会从源码详细的介绍⼀下。
@AutoConfigurationPackage
这个注解⼲了什么?这个需要看下源码,如下;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}
重要的还是@Import注解,导⼊了AutoConfigurationPackages.Registrar,这个类是⼲什么的?源码如下图:
其实就两个⽅法,但是的最重要的就是registerBeanDefinitions⽅法,但是这个⽅法不⽤看,肯定是注⼊Bean,这⾥的重点是注⼊哪些Bean,重点源码如下:
//获取扫描的包
new PackageImports(metadata).getPackageNames().toArray(new String[0])
跟进代码,主要逻辑都在#PackageImports.PackageImports()这个构造⽅法中,源码解析如下图:
从上⾯源码分析可以知道,这⾥扫描的包名是由两部分组成,分别如下:
1. 从@AutoConfigurationPackage注解中的两个属性解析得来的包名。
2. 注解AutoConfigurationPackage所在的包名,即是@SpringBootApplication所在的包名。spring ioc注解
@AutoConfigurationPackage默认将主配置类(@SpringBootApplication)所在的包及其⼦包⾥⾯的所有组件扫描到IOC容器中。
@Import(AutoConfigurationImportSelector.class)
这个注解不⽤多说了,最重要的就是AutoConfigurationImportSelector,我们来看看它的继承关系,如下图:
这个类的继承关系还是挺简单的,实现了Spring中的xxAware注⼊⼀些必要的组件,但是最值得关⼼的是实现了⼀个DeferredImportSelector这个接⼝,这个接⼝扩展了ImportSelector,也改变了其运⾏的⽅式,这个在后⾯章节会介绍。
「注意」:这个类会导致⼀个误区,平时看到xxxSelector已经有了反射弧了,肯定会在selectImports()⽅法上DEBUG,但是这个类压根就没执⾏该⽅法,我第⼀次看也有点怀疑⼈⽣了,原来它⾛的是DeferredImportSelector的接⼝⽅法。
其实该类真正实现逻辑的⽅法是process()⽅法,但是主要加载⾃动配置类的任务交给了getAutoConfigurationEntry()⽅法,具体的逻辑如下图:
上图的逻辑很简单,先从spring.factories⽂件中获取⾃动配置类,在去掉@SpringBootApplication中定义排除的⾃动配置类。
上图中的第④步就是从META-INF/spring.factories中加载⾃动配置类,代码很简单,在上⼀篇分析启
动流程的时候也有很多组件是
从spring.facotries⽂件中加载的,代码都类似。
在springboot-autoconfigure中的spring.facotries⽂件内置了很多⾃动配置类,如下:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.t.ConfigurationPropertiesAutoConfiguration,\
org.springframework.t.LifecycleAutoConfiguration,\
org.springframework.t.MessageSourceAutoConfiguration,\
org.springframework.t.PropertyPlaceholderAutoConfiguration,\
................
了解了Spring Boot如何加载⾃动配置类,那么⾃定义⼀个⾃动配置类也是很简单了,后续章节教你如何定制⾃⼰的⾃动配置类,⾥⾯还是有很多门道的.....
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论