其他分享
首页 > 其他分享> > @Import注解的作用

@Import注解的作用

作者:互联网

在@Import注解的参数中可以填写类名,例如@Import(Abc.class),根据类Abc的不同类型,spring容器有以下四种处理方式:

spring源码版本:5.0.5.RELEASE

跟踪spring容器是如何处理Import注解的,容器初始化一般从AbstractApplicationContext类的refresh开始,其它过程跳过,直接通过堆栈到相关的地方;

doProcessConfigurationClass:300, ConfigurationClassParser {org.springframework.context.annotation}
processConfigurationClass:245, ConfigurationClassParser {org.springframework.context.annotation}
parse:194, ConfigurationClassParser {org.springframework.context.annotation}
doProcessConfigurationClass:293, ConfigurationClassParser {org.springframework.context.annotation}
processConfigurationClass:245, ConfigurationClassParser {org.springframework.context.annotation}
parse:202, ConfigurationClassParser {org.springframework.context.annotation}
parse:170, ConfigurationClassParser {org.springframework.context.annotation}
processConfigBeanDefinitions:316, ConfigurationClassPostProcessor {org.springframework.context.annotation}
postProcessBeanDefinitionRegistry:233, ConfigurationClassPostProcessor {org.springframework.context.annotation}
invokeBeanDefinitionRegistryPostProcessors:273, PostProcessorRegistrationDelegate {org.springframework.context.support}
invokeBeanFactoryPostProcessors:93, PostProcessorRegistrationDelegate {org.springframework.context.support}
invokeBeanFactoryPostProcessors:694, AbstractApplicationContext {org.springframework.context.support}
refresh:532, AbstractApplicationContext {org.springframework.context.support}
ConfigurationClassParser是解析@PropertySources,@ComponentScan,@Import,@ImportResource,@Bean注解的地方
在ConfigurationClassParser#parse中
    public void parse(Set<BeanDefinitionHolder> configCandidates) {
        //稍后执行的parse方法中,所有DeferredImportSelector实现类都会被放入集合deferredImportSelectors中
        this.deferredImportSelectors = new LinkedList<>();

        for (BeanDefinitionHolder holder : configCandidates) {
            BeanDefinition bd = holder.getBeanDefinition();
            try {
                if (bd instanceof AnnotatedBeanDefinition) {
                  //在这个parse方法中,所有DeferredImportSelector实现类都会被放入集合deferredImportSelectors中,它们的selectImports方法不会被执行,而其他ImportSelector实现类的selectImports都会被执行
                    parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
                }
                else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                    parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
                }
                else {
                    parse(bd.getBeanClassName(), holder.getBeanName());
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                        "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
            }
        }

        //此方法内,会将集合deferredImportSelectors中的所有对象取出来执行其selectImports方法
        processDeferredImportSelectors();
    }

查看处理@import的地方

    protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
            throws IOException {
        ......

        // Process any @Import annotations
        processImports(configClass, sourceClass, getImports(sourceClass), true);

        ......
    }

跟踪查看getImports就是递归取类的@Import注解的,取到后在processImports方法中进行处理:

    private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
            Collection<SourceClass> importCandidates, boolean checkForCircularImports) {

        if (importCandidates.isEmpty()) {
            return;
        }

        if (checkForCircularImports && isChainedImportOnStack(configClass)) {
            this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
        }
        else {
            this.importStack.push(configClass);
            try {
                for (SourceClass candidate : importCandidates) {
                  //如果是ImportSelector接口的实现类,就在此处理
                    if (candidate.isAssignable(ImportSelector.class)) {
                        // Candidate class is an ImportSelector -> delegate to it to determine imports
                        Class<?> candidateClass = candidate.loadClass();
                        //实例化这些ImportSelector的实现类
                        ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
                        //如果这实现类还实现了BeanFactoryAware、EnvironmentAware这些接口,就要先执行这些接口中声明的方法
                        ParserStrategyUtils.invokeAwareMethods(
                                selector, this.environment, this.resourceLoader, this.registry);
                        //如果这个实现类也实现了DeferredImportSelector接口,就被加入到集合deferredImportSelectors中,在解析完成后在执行
                        if (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
                            this.deferredImportSelectors.add(
                                    new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
                        }
                        else {
                          //注意,这一行是关键代码!!!执行实现类的selectImports方法
                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                            Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
                            processImports(configClass, currentSourceClass, importSourceClasses, false);
                        }
                    }
                    //处理ImportBeanDefinitionRegistrar的实现类
                    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 {
                        // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
                        // process it as an @Configuration class
                        this.importStack.registerImport(
                                currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                        processConfigurationClass(candidate.asConfigClass(configClass));
                    }
                }
            }
            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();
            }
        }
    }

小结如下:

标签:DeferredImportSelector,springframework,ImportSelector,context,org,Import,注解,作用,C
来源: https://www.cnblogs.com/grasp/p/11906642.html