spring boot自动装配之@EnableAutoConfiguration详解
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对象了。
- Spring Boot自动配置详解
- SpringBoot SpringApplication底层源码分析与自动装配
- Spring boot中@Conditional和spring boot的自动配置实例详解
- 深入理解SpringBoot之自动装配
- Spring/SpringBoot自动装配的三种方式
- 深入理解SpringBoot之自动装配
- 详解jenkins自动部署springboot应用的方法
- spring boot学习二:Spring Boot自动装配分析与实战
- Spring自动装配与扫描注解代码详解
- 一步步从Spring Framework装配掌握SpringBoot自动装配
- spring boot 源码解析40-CounterService,GaugeService默认自动装配解析
- Java注解机制之Spring自动装配实现原理详解
- [Spring开发笔记]Spring中自动装配详解(协作者关系)
- 深入浅析SpringBoot中的自动装配
- spring入门教程之bean的继承与自动装配详解
- Spring Boot实战教程之自动配置详解
- Spring自动装配详解
- 关于SpringBoot中基于条件的自动装配
- Spring@Autowired注解与自动装配
- spring boot cache理论详解