这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战
前言
之前的文章中,我们实现Spring Boot的下自定义注解功能,想必对于Spring Boot大家都应该很了解。在项目的启动类上,我们有注意到@SpringBootApplication
这个注解,之前文章里也有介绍的其实它是由@SpringBootConfiguration
,@EnableAutoConfiguration
,@ComponentScan
这三个注解组成的。@ComponentScan
介绍过了,它的作用是指定扫描包的范围;@SpringBootConfiguration
这个注解我们之后文章中再来详细介绍。本文主要重点深入@EnableAutoConfiguration
这个注解,看看Spring Boot的自动装配是如何实现的。
@EnableAutoConfiguration注解
首先我们看下@EnableAutoConfiguration
这个注解源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
好吧,里面又是由其它注解组成,我们有看到它通过@Import
来引入了AutoConfigurationImportSelector
这个类,接下来我们再进入看下这个类的源码
首先该类实现了DeferredImportSelector
接口,而这个接口继承了ImportSelector
可以看到它的作用就是为了导入@Configuration
的配置项,而DeferredImportSelector
是延期导入,当所有的@Configuration
都处理过后才会执行。好了,我们再回过头看下AutoConfigurationImportSelector
类的selectImports
方法:
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
首先if (!this.isEnabled(annotationMetadata))
这里判断是否进行自动装配,如果是的话那么通过loadMetadata
方法去META-INF/spring-autoconfigure-metadata.properties读取元数据与元数据的相关属性
接着我们看getCandidateConfigurations
方法,它会读取META-INF/spring.factories下的EnableAutoConfiguration的配置,紧接着在进行排除与过滤,为什么要过滤呢?原因是很多的@Configuration其实是依托于其他的框架来加载的,如果当前的classpath环境下没有相关联的依赖,则意味着这些类没必要进行加载,所以,通过这种条件过滤可以有效的减少@configuration类的数量从而降低SpringBoot的启动时间。
之后我们得到需要装配的类。最后让所有配置在META-INF/spring.factories下的AutoConfigurationImportListener执行AutoConfigurationImportEvent事件。
至此,我们差不多看到了自动装配的整个流程。
总结
其实在getCandidateConfigurations
方法中,我们有看到熟悉的SpringFactoriesLoader
,因此自动装配还是利用了SpringFactoriesLoader
来加载META-INF/spring.factoires
文件里所有配置的EnableAutoConfgruation
,它会经过exclude和filter等操作,最终确定要装配的类。