背景
springboot在启动过程中会自动加载配置文件中的类供后续使用,这个过程称为自动装配
引入@Import注解
springboot的启动类加入注解@SpringBootApplication,@SpringBootApplication注解中包含@EnableAutoConfiguration注解,@EnableAutoConfiguration这个注解中包含@Import(AutoConfigurationImportSelector.class)注解,springboot就是通过解析这个@Import注解来实现自动装配的
原理分析
- springboot启动时会调用spring的核心方法refresh(),在refresh方法中调用invokeBeanFactoryPostProcessors(),这个方法用来执行beanFactory的一些后置处理器,处理一些比如注解解析的工作。这些后置处理器中有一个ConfigurationClassPostProcessor处理器,就是专门来解析注解的
- @Import注解解析
@Nullable
protected final SourceClass doProcessConfigurationClass(
ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
throws IOException {
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
//处理@Component注解及其内部类
}
// Process any @PropertySource annotations
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
//处理@PropertySource注解
}
// Process any @ComponentScan annotations
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
//处理@ComponentScan注解
}
// Process any @Import annotations
//注解@Import注解
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
// Process any @ImportResource annotations
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
//处理@ImportResoure注解
}
// Process individual @Bean methods
//处理@Bean注解
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
//处理接口的缺省方法
processInterfaces(configClass, sourceClass);
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
//处理父类信息
}
// No superclass -> processing is complete
return null;
}
通过getImports(sourceClass)方法递归处理,获取所有@Import注解
private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
throws IOException {
if (visited.add(sourceClass)) {
for (SourceClass annotation : sourceClass.getAnnotations()) {
String annName = annotation.getMetadata().getClassName();
if (!annName.equals(Import.class.getName())) {
//此处为递归处理,获取所有的@Import注解,放到imports集合中
collectImports(annotation, imports, visited);
}
}
imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
}
}
执行processImports方法(注:只列出核心代码)
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
boolean checkForCircularImports) {
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
this.importStack.push(configClass);
try {
//遍历所有import进来的类
for (SourceClass candidate : importCandidates) {
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
this.environment, this.resourceLoader, this.registry);
Predicate<String> selectorFilter = selector.getExclusionFilter();
if (selectorFilter != null) {
exclusionFilter = exclusionFilter.or(selectorFilter);
}
if (selector instanceof DeferredImportSelector) {
//自动装配所需的selector实现了DeferredImportSelector接口,所以要加入到延迟处理的集合,后续处理
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else { //否则就会立即执行
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
//递归处理,import的类的类的类。。。
processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}
}
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
//。。。
}
else {
//。。。
}
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configClass.getMetadata().getClassName() + "]", ex);
}
finally {
this.importStack.pop();
}
}
}
处理延迟列表中的类,此时为AutoConfigurationImportSelector,调用getCandidateConfigurations()方法,获取spring.factories配置文件中的内容,根据getSpringFactoriesLoaderFactoryClass()方法返回的类文件作为key来筛选配置文件内容
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//调用getCandidateConfigurations()方法获取配置文件spring.factories中的类路径
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
- spring.factories文件容截取
# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration
- 取出对应value值之后,在根据一定的规则过滤,最后留下一批springboot需要的大概是25个,在遍历解析这些类上的注解,解析完之后,将对应的属性值赋值给beanDefinition,用户之后的初始化操作
- 总结:
- 解析@Import注解,递归拿到AutoConfigurationImportSelector类,放入延迟处理列表deferredImportSelectors中
- 处理AutoConfigurationImportSelector。调用getCandidateConfigurations()方法,获取org.springframeword.boot.spring-boot-autoconfigure的jar包下META-INF/spring.factories配置文件中的内容
- 调用getSpringFactoriesLoaderFactoryClass()方法,返回的类文件的权限顶名做为key,去配置文件中value,拿到value列表之后,根据规则过滤,封装成AutoConfigurationEntry对象
- 继续处理这些从配置文件拿到的类,和上面的步骤一样,解析类上的注解
- 解析之后,合并到beanDefinition中,供后续的操作使用