@SpringBootApplication 注解流程解析
前言:上文已经分析了,springboot的入口函数的实现过程,如何启动 ioc容器,如何监听等等。
**本文继续分析第二部分,springboot中的@SpringbootApplication 注解如何实现的自动配置 **
废话少说上 @SpringbootApplication 源码
@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
我们逐个分析其中的注解:**@ComponentScan**
是Spring 中的注解,默认扫描注解类的包路径不再多说了
**@SpringBootConfiguration**
** **这个注解是springboot中的,我们看看这个注解的源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
看完我们就很清楚了,熟悉的注解 @Configuration
** **这个作用我们也不在多说。用来标注配置类的。
**@EnableAutoConfiguration**
这是我们的主要实现注解,我们来看源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration
看到 @import
注解导入了bean AutoConfigurationImportSelector.class 和@AutoConfigurationPackage
我们接下来分开看一看。
1.@Import(AutoConfigurationImportSelector.class)
我们看下 AutoConfigurationImportSelector 类的核心代码
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
// 核心逻辑1 在spring扫描 configuration 类的时侯调用
@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
// 获取自动配置类
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
//核心逻辑2 获取过滤后的自动配置类
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
// 1. 获取@SpringbootApplication注解信息
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 2. 获取 spring.factories 文件中的 EnableAutoConfiguration 类配置
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 3. 将配置类使用set去重
configurations = removeDuplicates(configurations);
// 4. 过滤掉需要排除的 配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
// 5. 过滤器 过滤 AutoConfigurationImportFilter.class
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
// 返回自动配置类信息
return new AutoConfigurationEntry(configurations, exclusions);
}
}
因为 实现了 DeferredImportSelector 类,所以在spring 扫描import组件的时侯会延迟等待其他扫描完成后执行
process方法。
看下 spring容器启动过程中ConfigurationClassParser#processImports 的源码
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
总结:看到这里我们可以了解自动配置类是如何被发现的。通过扫描路径下的 “META-INF/spring.factories” 文件中 EnableAutoConfiguration.class
的对应配置,然后通过去重,排除,过滤几大步骤 ,然后会通过spring源码中的 ConfigurationClassPostProcessor 步骤 ,将定义信息进行注入ioc容器
// 将通过解析@Bean,@Import等注解得到相关信息解析成bd被注入到容器中
this.reader.loadBeanDefinitions(configClasses);
2.@AutoConfigurationPackage
这个组合注解主要是@Import(AutoConfigurationPackages.Registrar.class),它通过将Registrar类导入到容器中,而Registrar类作用是扫描主配置类同级目录以及子包,并将相应的组件导入到springboot创建管理的容器中;