自动装配,简单来说就是自动把第三方组件的 Bean 装载到 Spring IOC 器里面,不需要开发人员再去写 Bean 的装配配置。在 Spring Boot启动类加上@SpringBootApplication 注解就可以实现自动装配。@SpringBootApplication 是一个复合注解,真正实现自动装配的注解是@EnableAutoConfiguration。
@SpringBootApplication
@ComponentScan(basePackages = {"com...."})
public class SmartApplication {
public static void main(String[] args) {
SpringApplication.run(SmartApplication.class, args);
}
}
@EnableAutoConfiguration也是一个复合注解,内部@import注解引入了一个AutoConfigurationImportSelector 自动配置类选择器。
ps:@SpringbootConfiguration 是 Spring Boot 提供的一个注解,继承了 @Configuration 的功能,可以理解等同于@Configuration。
@ComponentScan自动扫描并加载符合条件的Bean。其实,如果启动类中不需要增加配置内容,也不需要指定扫描路径,可以使用@EnableAutoConfiguration来替代@SpringBootApplication,也可以完成启动。
@AutoConfigurationPackage // 指定扫描的基础包,SpringBoot将会扫描该包及其子包中的所有类,以查找和加载自动配置类和其他组件
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
AutoConfigurationImportSelector类中实现了ImportSelector接口,并重写了其selectImports方法。
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
getAutoConfigurationEntry方法中调用了一个关键方法:getCandidateConfigurations,获取所有候选配置信息。
//可以先看下获取的大致流程,而后进入查看器方法内部的具体实现
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
//1. 从注解元数据中获取注解的相应属性,将相应属性存储到map中返回
//1.1 AnnotationAttributes是一个Map集合,其继承了LinkedHashMap
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//2. 获取自动配置候选项
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//2.1 通过removeDuplicates()方法对自动配置的类名进行去重处理
configurations = removeDuplicates(configurations);
//3. 根据注解元数据和注解属性获取到需排除配置项
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//3.1检查是否有无效的排除类存在
checkExcludedClasses(configurations, exclusions);
//3.2从自动配置候选项中删除需要排除的配置项
configurations.removeAll(exclusions);
//4. 调用getConfigurationClassFilter()方法获取到获取配置的所有AutoConfigurationImportFilter的实现类(对spring.factories进行过滤的类),调用filter方法对配置文件进行筛选,而后返回需要自动配置的类
configurations = getConfigurationClassFilter().filter(configurations);
//5. 根据spring.factories文件中的AutoConfigurationImportListener事件监听器发布并处理监听事件,最后根据多次过滤、判重返回配置类合集
fireAutoConfigurationImportEvents(configurations, exclusions);
//6. 创建一个新的配置实体ConfigurationEntry并返回,包含需要配置项configurations,和被排除配置项exclusions
return new AutoConfigurationEntry(configurations, exclusions);
}
点开getCandidateConfigurations方法,源代码如下:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = new ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()));
ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).forEach(configurations::add);
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
SpringFactoriesLoader会加载META-INF/spring.factories文件,该文件以键值方式存储,将EnableAutoConfiguration下的所有配置类装载到容器中去。
如getAutoConfigurationEntry方法的源代码,在getCandidateConfigurations执行后,进行去重、排除、过滤等操作。