Spring-@Import介绍

一、@Import作用总结

//使用方式
@Import(xxx.class)
@Configuration
public class AppConfigClassTest {
}

1、如果xxx.class这个类实现了ImportSelector,执行重写的方法selectImports, 该方法返回一个Class集合,并且这些Class集合会被注入到spring里面去。关于ImportSelector接口的使用和介绍请看这篇文章@ImportSelector注解

2、如果xxx.class这个类实现了ImportBeanDefinitionRegistrar接口,执行重写ImportBeanDefinitionRegistrar接口里面BeanDefinitionRegistry方法,该方法经常用来往Spring注册Bean,关于ImportBeanDefinitionRegistrar可以看我这偏文章ImportBeanDefinitionRegistrar接口介绍

3、否者就把这个xxx.class当成Bean注册到Spring里面去

下面介绍下@Import源码是如何处理上面三种情况的。这里说明一下Spring处理@Import是在ConfigurationClassPostProcessor这个后置处理里面触发,spring为什么这么设计,ConfigurationClassPostProcessor这个后置处理器不是处理@Configuration注解的吗? 因为@Import的使用要和@Configuration组合一起使用,所以在解析带有@Configuration注解的类时,会同时解析该类上面是否包含@Import注解、是否包含@Bean注解的方法属性等。

//这里就直接跳到ConfigurationClassPostProcessor处理@Import注解的逻辑上
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, 
                Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) {

    //如果importCandidates为空直接return,为什么会有这个,因为下面代码可能会递归调用processImports,就比如Import一个类,这个类也带了@Import注解,那就会在调用一次processImports方法
    if (importCandidates.isEmpty()) {
        return;
    }

    for (SourceClass candidate : importCandidates) {
        if (candidate.isAssignable(ImportSelector.class)) {
        	//1、import的类,实现了ImportSelector接口
            Class<?> candidateClass = candidate.loadClass();
            //利用反射Class实例化对象,这个对象不是代理对象不要搞混了。
            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) {
                this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
            } else {
            	//调用ImportSelector接口里面的selectImports方法,拿到返回值Class集合。在通过递归的方式嗲用processImports挨个解析每一个Class
                String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
            }
        } else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
            //2、import的类实现了ImportBeanDefinitionRegistrar接口	
            Class<?> candidateClass = candidate.loadClass();
            //通过反射实例化ImportBeanDefinitionRegistrar的实现类,并添
            //加到Map中,这个Map里面存的都是ImportBeanDefinitionRegistrar实现类,后面会有其他处理统一处理。
            ImportBeanDefinitionRegistrar registrar =
                    ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
                            this.environment, this.resourceLoader, this.registry);
                            
            configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
        } else {
            //3、ImportSelector和ImportBeanDefinitionRegistrar都没有实现
            this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
            //进一步解析其他注解,比如@Component @Import等最后会把configClass注册到Spring容器中。
            processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
        }
    }
}

你可能感兴趣的:(spring,spring,import,ImportSelector)