Spring注解--@Import

例子

@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.classImportBeanDefinitionRegistrar.class的类,按照一个被@Configuration注解装饰的类去解析(有没有@Component、@PropertySources等等注解)。

总结

SpringBoot在处理@Configuration注解时,会先处理@ComponentScans@Component@Import等等注解。在处理@Import注解会根据导入类是否实现ImportSelector.classImportBeanDefinitionRegistrar.class做出不同的处理。尤其是对ImportSelector.class子类的处理,其中涉及到SpringBoot自动加载的秘密。@SpringBootApplication是一个组合注解,其中的@EnableAutoConfiguration导入了AutoConfigurationImportSelector.class,AutoConfigurationImportSelector类是实现自动注入的一个关键

原文地址:https://www.cnblogs.com/-1007813544/p/spring-zhu-jieimport.html