1. 配置
思路:为什么加了个注解就能自动配置?首先从注解找线索。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
// 下面这个注解
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
// 省略
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
// 导入自动配置导入选择器
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
// 省略
}
因为注解具有传递性, EnableAutoConfiguration
注解是 Spring Boot 的全局开关,如果把这个注解去掉,则一切 Starter 都会失效,即约定大于配置。
在它上面导入了一个类@Import(AutoConfigurationImportSelector.class)
,翻译过来即自动配置导入选择器。
核心逻辑
- 利用spring的
BeanFactoryPostProcessor 扩展点
加载更多的场景 BeanDefinition。这里使用的是ConfigurationClassPostProcessor
。 - 这个处理器会解析
配置类
(标注了@Configuration注解的类),解析里面的@Import注解导入的AutoConfigurationImportSelector类
。 - 这个类负责导入场景配置。
利用的是getAutoConfigurationEntry方法
里面的getCandidateConfigurations方法
里面的SpringFactoriesLoader.loadFactoryNames
加载META-INF/spring.factories
文件。
总结
原理就是启动容器的时候,按照抽象容器类中refresh方法定义的启动流程:
- 先加载配置类和Bean定义。
- 之后会调用
Bean工厂后置处理器
来处理Bean定义,其中包含Bean的注解,当处理到@Import
的时候,由于内部类实现了DeferredImportSelector.Group
接口,所以会调用到内部类的process
方法,从而触发自动配置的加载。
网友评论