您的位置:首页 > 编程语言 > Java开发

spring boot自动装配之@EnableAutoConfiguration详解

2019-02-14 14:58 666 查看

1、@EnableAutoConfiguration作用

@EnableAutoConfiguration用于类或接口上,在spring boot中注解位于@SpringBootApplication注解上

[code]@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
……
}

 当spring boot扫描到@EnableAutoConfiguration注解时则会将spring-boot-autoconfigure.jar/META-INF/spring.factories文件中org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的value里的所有xxxConfiguration类加载到IOC容器中。而xxxAutoConfiguration类一般都会有@ConditionalOnxxx注解,通过这些条件注解来判断是否真正的创建xxxConfiguration对象。spring boot的各种spring-boot-starter-xxx.jar也正是居于此注解来达到自动装配的目的。

@ConditionalOnxxx常见注解如下:

@ConditionalOnClass classpath中存在该类时起效
@ConditionalOnMissingClass classpath中不存在该类时起效
@ConditionalOnBean DI容器中存在该类型Bean时起效
@ConditionalOnMissingBean DI容器中不存在该类型Bean时起效
@ConditionalOnSingleCandidate DI容器中该类型Bean只有一个或@Primary的只有一个时起效
@ConditionalOnExpression SpEL表达式结果为true时
@ConditionalOnProperty 参数设置或者值一致时起效
@ConditionalOnResource 指定的文件存在时起效
@ConditionalOnJndi 指定的Java版本存在时起效
@ConditionalOnWebApplication Web应用环境下起效
@ConditionalOnNotWebApplication 非Web应用环境下起效

2、spring boot处理@EnableAutoConfiguration源码分析

通过《spring boot自动装配原理之@ComponentScan详解》一文我们知道spring boot自动装配的过程都是在ConfigurationClassPostProcessor这个BeanFactoryPostProcessor类中完成的。

核心流程如下:

[code]public class ConfigurationClassPostProcessor {
…………
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);

Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
//1、该方法执行完后会将这pring-boot-autoconfigure.jar/META-INF/spring.factories文件
//中org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的value值全部封装
//成ConfigurationClass对象存在parser对象的configurationClasses属性中。
parser.parse(candidates);
parser.validate();
//2、取出ConfigurationClass对象
configClasses.removeAll(alreadyParsed);
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());

// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
//3、将ConfigurationClass转换成ConfigurationClassBeanDefinition并注册到beanFactory中,
//以供后面创建具体的对象,该方法也很复杂,本文不深入研究
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
…………
}

下面是重点过程方法的拆分,断点走向:

ConfigurationClassPostProcessor.parse(……) --> this.deferredImportSelectorHandler.process(……) --> AutoConfigurationImportSelector.getCandidateConfigurations(……) --> SpringFactoriesLoader.loadFactoryNames(……) --> ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(……)

断点进入parse方法:

[code]public void parse(Set<BeanDefinitionHolder> configCandidates) {
……
this.deferredImportSelectorHandler.process();
}

 进入 this.deferredImportSelectorHandler.process();断点一直跟踪到AutoConfigurationImportSelector的下面方法

[code]protected AutoConfigurationEntry getAutoConfigurationEntry(
AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//这个列表对应pring-boot-autoconfigure.jar/META-INF/spring.factories文件中
//org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的value值
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
……
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
//加载属性文件中xxxAutoConfiguration配置
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
……
return configurations;
}

 

this.reader.loadBeanDefinitions(configClasses);方法执行完成后的截图如下:

当所有xxxConfiguration类转换成BeanDefinition对象并注册到DefaultListableBeanFactory后,后面就可以创建具体的bean对象了。

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: