官网介绍
先来看看官网是怎么定义这个自动装配的~
Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added
可以看到这里说,当你引入了某个 jar
依赖包时,Springboot
会尝试根据这个依赖去自动配置 Spring
应用程序。
You need to opt-in to auto-configuration by adding the
@EnableAutoConfiguration
or@SpringBootApplication
annotations to one of your@Configuration
classes.
而且这里还说明了,你应该在 一个配置类 @Configuration
上选择 @EnableAutoConfiguration
和 @SpringBootApplication
这其中的一个注解,来让自动配置生效.
那么,知道这些信息后,我们就开始愉快的看源码环节了~ 冲冲冲!😄
对了,探索的 Springboot
版本为 2.4.5
@SpringBootApplication
来到 @SpringBootApplication
注解中,可以发现它是一个组合注解,除了前面四个基本的元注解外,还有下面这三个 @SpringBootConfiguration
, @EnableAutoConfiguration
,@ComponentScan
源码如图
@SpringBootConfiguration
我们先来看这第一个注解,如图,可以发现它其实是一个 @Configuration
注解,
@Configuration
注解的作用是将其作为一个配置类,来配置 Spring
的上下文,相当于 Spring
的 XML
配置文件中的 <beans>
源码如图
@ComponentScan
这个的作用就是 扫描指定路径下的组件,并加入到 IOC
容器 中,相当于
Spring
的 XML
配置文件中的 <context:component-scan/>
源码如图
可以发现它里面有一个 @Repeatable(ComponentScans.class)
注解,表示可重复使用@ComponentScan
注解
注意,这里会按照我们自定义的方式去排除一些类,具体是通过实现 TypeFilter
接口并重写 match
方法来实现 。
小细节
这里还有个点要注意下~😄
AutoConfigurationExcludeFilter
会检查配置类,如果该配置类和 META-INF/spring.factories
文件中的 EnableAutoConfiguration
对应的配置类一样的话,会被排除掉~
@EnableAutoConfiguration
终于,来到本文的重点了 🐷
看到它的名字就知道它就是这个 自动配置 的主角了
源码如图
可以发现它是一个组合注解
先来看看这个注解1@AutoConfigurationPackage
@AutoConfigurationPackage
从名字就可以看出它是一个 自动配置包路径 的注解
源码如图
从这段注释我们可以发现,当没有配置这个 basePackages
或者
basePackageClasses
时,这个类就会自动将该注解所在的包作为基本路径进行注册
接着,我们再来看看这个框框里的内容~
@Import(AutoConfigurationPackages.Registrar.class)
🐷
@Import
先来看看这个注解的作用吧😋
源码如图
可以发现它的作用也很简单,就是导入组件,比如常见的 @Configuration
类或者ImportSelector
和 ImportBeanDefinitionRegistrar
的实现类,或者其他一些常规的组件如 @Component
,@Service
等等
Registrar
继续看看这个 @Import(AutoConfigurationPackages.Registrar.class)
,可以发现该注解导入的是 Registrar
类 🐷 , 那么我们继续探索下,看看它干了什么~😄
源码如图
从该类的注解可以看出,它的作用是通过 ImportBeanDefinitionRegistrar
**来保存这个基本包的路径的 **
那么,讲完第一点 ,我们简单了解到这个 @AutoConfigurationPackage
就是用来配置基本包 ,我们接着再来看看第二点,这个 @Import(AutoConfigurationImportSelector.class)
注解。
我们可以发现它导入了 AutoConfigurationImportSelector
类。
AutoConfigurationImportSelector
看这个名称,可以大概知道它是一个 组件选择器
关键步骤介绍
process
这个方法在获取这些 Import
类时会被调用,具体可以看结尾的流程图~
getAutoConfigurationEntry
获取自动配置实体类 ,里面还有本文的重点~
getCandidateConfigurations
来到这里,可以发现它调用到这个 SpringFactoriesLoader
,这里就不得不提下这个 Springboot
的 SPI
机制了,另外它和我们上文(服务发现机制SPI居然是破坏者?! )中提到的 Java Spi 有什么不同呢 ?
再继续往下看一下~😝
Springboot SPI机制
老规矩,看一眼注释先 哈哈😄
spring.factories 文件
举个栗子😄
# Run Listeners org.springframework.boot.SpringApplicationRunListener=\ org.springframework.boot.context.event.EventPublishingRunListener 复制代码
可以发现它加载的是 META-INF/spring.factories
这个文件 ,相比 java
的 META-INF/services
,有以下的不同点:
- 从名字上就可以发现很大的不同( 一个是
factories
文件,一个是以接口全名命名的文件 )。
spring.factories
以一个聚合的作用,把相应的接口和实现类以 key = value 形式展现在spring.factories
文件中。
spring.factories
中的所有配置项会加载到我们的缓存中,以Map<String,List<String>>
形式存储,但不是所有的都会被实例化,被加载到IOC
容器中,除了必要的类外(EventPublishingRunListener
等 ),还有满足特定条件下的自动配置类会被加载到IOC
容器中
满足特定条件 ☞ 比如有没有使用到这个依赖( pom
中的 starter
)
自动配置类 ☞ 指以 AutoConfiguration
结尾的那些类
可以发现这种按需实现的机制比java的一股脑实现灵活多了~ 😄
实例解析
比如 这里从 spring.factories
文件中加载了130个自动配置类
但是实际使用中,经过过滤后只有这 30 个了
这里还根据 优先级 做了一些排序~ 🐷
自动装配流程图
这里只摘了一些关键步骤~ ,具体流程太长了 ,得从 SpringApplication
源码中的 refreshContext(context);
这里就先不介绍啦,后面有时间再写一下分享下这个 [[Springboot
源码的启动过程]]
同颜色的类名和方法块对应~
图中左下角的 processImports
方法,就是将这些自动配置类进行实例化,包括配置类里面的 @Import
, @Bean
等 ,一步步加载到 Spring
的 IOC
容器中。
总结
一. Springboot
的自动装配很重要的一点就是,就是要在配置类上开启 @EnableAutoConfiguration
或者 @SpringBootApplication
注解,来让自动配置生效。
二. 自动配置的核心是 Springboot
的 SPI
机制 ,以及组件选择器AutoConfigurationImportSelector
,具体是通过其中的 getAutoConfigurationEntry
方法来获取 SPI
中的自动配置类并进行过滤,最后通过 processImports
将配置类加载到 IOC
容器中,完成自动配置