Spring boot的自动装配可以从官方文档得出答案:Spring boot自动装配的特性可以由@EnableAutoConfiguration来激活。@SpringBootApplication又是包含以下三个注解:@SpringBootConfiguration、@ComponentScan、@EnableAutoConfiguration。因此@SpringBootApplication也是可以进行自动装配的。(从这里可以看出@SpringBootApplication注解不是spring boot项目的必备注解,可以通过下面的案例进行证实)
@EnableAutoConfiguration
public class WmGameApplicationTests {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(ConfigBean.class);
/*String [] beanNames=annotationConfigApplicationContext.getBeanNamesForType(Color.class);
Map mapBean= annotationConfigApplicationContext.getBeansOfType(Color.class);
for(String item:beanNames){
System.out.println("bean名称:"+item+"--- 输出bean对象:"+mapBean.get(item));
}*/
System.out.println("当前spring应用上下文所在注册bean名称");
Stream.of(annotationConfigApplicationContext.getBeanDefinitionNames())
.map(name -> "\t" + name)
.forEach(System.out::println);
annotationConfigApplicationContext.close();
}
}
输出结果为:
当前spring应用上下文所在注册bean名称
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
只是@SpringBootApplication可以减少多注解带来的配置成本,如配置@SpringBootApplication的scanBasePackages等同于@ComponentScan#basePackages
一、替换自动装配
在开发人员在任意一处定义配置类,从而可以覆盖自动装配的组件。如:通过自定义的dataSource替换默认的数据源。
二、失效自动装配
在注解@EnableAutoConfiguration中可以看到,提供了几个参数:exclude()和excludeName()。
三、spring boot的自动装配原理
依照@Enable模块驱动模式,@EnableAutoConfiguration的实现肯定是"@import"importSelector、importBeanDefinitionRegirstar的实现类。查看源码可以知道这个实现类是:AutoConfigurationImportSelector
@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 {};
}
仔细跟踪AutoConfigurationImportSelector类,最上层的接口是importSelctor,重要的一个实现方法是selectorImports方法:
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.filter(configurations, autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return StringUtils.toStringArray(configurations);
}
}
可以对上述的代码进行猜测(大概知道每句代码的大体意思)。
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);//就是获取自动装配的元数据(通过英文意思知道),具体是什么可以不做深究。
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);// 获取标注@EnableAutoConfiguration的元数据。
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);//获取候选的自动装配类集合
configurations = this.removeDuplicates(configurations); // 移除重复对象
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);//需要排除的类的名单
configurations = this.filter(configurations, autoConfigurationMetadata); // 将排除后的对象进行过滤,注意:autoConfigurationMetadata 是第一步骤获取的自动装配的对象,因为过滤信息应该是保存在autoConfigurationMetadata 对象中的。
this.fireAutoConfigurationImportEvents(configurations, exclusions);// 触发了导入事件,导入的对象就是经过过滤后的对象集合。
问题:
上述的猜测不敢保证全对,但是基本知道方法的作用,可以得出以下结论:
1、getCandidateConfigurations方法可以知道怎么装配组件,装配哪些组件?
答:getCandidateConfigurations方法根据MATA-INF/spring.factories资源内容作为propertise文件读取,合并到一个key为接口的全类名,value为接口的实现类的列表的map。如下图所示:
2、getExclusions可以知道怎么排除exclude配置的类?
答:getExclusions是根据在注解@EnableAutoConfiguration中配置的exclude和excludeName以及再配置文件配置的spring.autoconfigure.exclude累加到排除集合exclude.
概括如下:
1、通过springfactoriesLoader#loadFactoryNames方法读取所有MATA/INFO/Spring.factorise资源中@EnableAutoConfiguration关联的自动装配class集合。
2、根据在注解@EnableAutoConfiguration中配置的exclude和excludeName以及再配置文件配置的spring.autoconfigure.exclude累加到排除集合exclude.
3、检查自动装配class排除集合是否合法。
4、排除候选自动装配集合排除名单。
5、过滤候选自动装配class集合下的class不存在的成员。