zoukankan      html  css  js  c++  java
  • 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类是实现自动注入的一个关键

  • 相关阅读:
    转载——关于scanf造成死循环
    转载——关于C#延时
    2013.02.13——笔记
    最近计划
    关于毕业设计——2013.4.12
    关于c#中combobox赋值问题
    使用DWE编辑对话框窗体
    Insert New Class (a2BusNew under BusItem)
    将TCE链接加入新工作通知(NewWorkAssignment,Sig)邮件中
    创建Relation并Add到数据库
  • 原文地址:https://www.cnblogs.com/-1007813544/p/spring-zhu-jieimport.html
Copyright © 2011-2022 走看看