例子
@Configuration
@Import(AssertionFailedException.class)
public class TestHuang {
@Bean
public TestDependOnBean testDependOnBean(){
return new TestDependOnBean("我是个参数");
}
}
@Import注解解析流程
//configClass、currentSourceClass是和TestHuang.class相关的参数
//importCandidates是@Import导入的类:AssertionFailedException.class
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
Collection<SourceClass> importCandidates, boolean checkForCircularImports) {
//如果没有@Import注解导入的类,直接return
if (importCandidates.isEmpty()) {
return;
}
//是否存在重复import()
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
//将需要解析的类(testHuang)存入队列中
this.importStack.push(configClass);
try {
//循环解析Import的类
for (SourceClass candidate : importCandidates) {
//【1】import类是ImportSelector.class的子类
if (candidate.isAssignable(ImportSelector.class)) {
// Candidate class is an ImportSelector -> delegate to it to determine imports
Class<?> candidateClass = candidate.loadClass();
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
ParserStrategyUtils.invokeAwareMethods(
selector, this.environment, this.resourceLoader, this.registry);
if (selector instanceof DeferredImportSelector) {
this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
}
else {
String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
processImports(configClass, currentSourceClass, importSourceClasses, false);
}
}
//【2】import类是ImportBeanDefinitionRegistrar.class的子类
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
// Candidate class is an ImportBeanDefinitionRegistrar ->
// delegate to it to register additional bean definitions
Class<?> candidateClass = candidate.loadClass();
ImportBeanDefinitionRegistrar registrar =
BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);
ParserStrategyUtils.invokeAwareMethods(
registrar, this.environment, this.resourceLoader, this.registry);
configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
}
else {
//【3】import类是一个普通的类
// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
// process it as an @Configuration class
//存入缓存
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
//把它当做一个@Configuration处理,相当于往IOC容器注册一个bean
processConfigurationClass(candidate.asConfigClass(configClass));
}
}
}
...
finally {
//弹出解析的类(testHuang)
this.importStack.pop();
}
}
}
【1】ImportSelector.class子类
ImportSelector
有个特殊的子类DeferredImportSelector
,实现了DeferredImportSelector的子类,会将它们存放在DeferredImportSelectorHandler#deferredImportSelectors链表中。
其他非实现DeferredImportSelector的子类,都会被调用selector.selectImports()
方法,收集selectImports()
方法返回的类,再递归调用processImports()
方法,避免遗漏import的类
deferredImportSelectors
链表中的selector在解析完@Configuration
注解后被调用。
一个应用在启动的过程的调用链SpringApplication#run()->refresh()->invokeBeanFactoryPostProcessors()->invokeBeanFactoryPostProcessors()->invokeBeanDefinitionRegistryPostProcessors()->ConfigurationClassParser#parse()
deferredImportSelectors
链表在parse()方法中被执行,细节请自行debug
【2】ImportBeanDefinitionRegistrar.class 子类
收集ImportBeanDefinitionRegistrar.class
的实现类,存放在ConfigurationClass#importBeanDefinitionRegistrars map对象中。
【3】普通类
对于既没有实现ImportSelector.class
和ImportBeanDefinitionRegistrar.class
的类,按照一个被@Configuration
注解装饰的类去解析(有没有@Component、@PropertySources等等注解)。
总结
SpringBoot在处理@Configuration
注解时,会先处理@ComponentScans
、@Component
、@Import
等等注解。在处理@Import
注解会根据导入类是否实现ImportSelector.class
,ImportBeanDefinitionRegistrar.class
做出不同的处理。尤其是对ImportSelector.class
子类的处理,其中涉及到SpringBoot自动加载的秘密。@SpringBootApplication
是一个组合注解,其中的@EnableAutoConfiguration
导入了AutoConfigurationImportSelector.class,AutoConfigurationImportSelector类是实现自动注入的一个关键