spring 对@Import注解的处理过程

Spring对注解的处理都发生在AbstractApplicationContext -> refresh() -> invokeBeanFactoryPostProcessors(beanFactory) -> ConfigurationClassPostProcessor -> postProcessBeanDefinitionRegistry()方法中。

springboot初始化的普通context(非web) 是AnnotationConfigApplicationContext, 在初始化的时候会初始化两个工具类, AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner 分别用来从 annotation driven 的配置和xml的配置中读取beanDefinition并向context注册, 那么在初始化 AnnotatedBeanDefinitionReader 的时候, 会向BeanFactory注册一个ConfigurationClassPostProcessor 用来处理所有的基于annotation的bean, 这个ConfigurationClassPostProcessor 是 BeanFactoryPostProcessor 的一个实现,springboot会保证在 invokeBeanFactoryPostProcessors(beanFactory) 方法中调用注册到它上边的所有的BeanFactoryPostProcessor

// Parse each @Configuration class
        ConfigurationClassParser parser = new ConfigurationClassParser(
                this.metadataReaderFactory, this.problemReporter, this.environment,
                this.resourceLoader, this.componentScanBeanNameGenerator, registry);

那么在 ConfigurationClassParser -> processConfigurationClass() -> doProcessConfigurationClass() 方法中我们找到了 (这里边的流程还是很清楚的, 分别按次序处理了@PropertySource, @ComponentScan, @Import, @ImportResource, 在处理这些注解的时候是通过递归处理来保证所有的都被处理了)

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

那接下来就看它到底是怎么做的 . 流程依然清晰 :
首先,判断如果被import的是 ImportSelector.class 接口的实现, 那么初始化这个被Import的类, 然后调用它的selectImports方法去获得所需要的引入的configuration, 然后递归处理
  其次, 判断如果被import的是 ImportBeanDefinitionRegistrar 接口的实现, 那么初始化后将对当前对象的处理委托给这个ImportBeanDefinitionRegistrar
  如果不是ImportSelector的子类,也不是ImportBeanDefinitionRegistrar 的子类,则当做@Configuration配置类去处理,将该类放入 this.importStack栈中,processConfigurationClass方法去递归解析

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) {
                    if (candidate.isAssignable(ImportSelector.class)) {
                    // 判断如果被import的是 ImportSelector.class 接口的实现, 那么初始化这个被Import的类, 然后调用它的selectImports方法去获得所需要的引入的configuration, 然后递归处理
                        // 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 (this.deferredImportSelectors != null && selector instanceof DeferredImportSelector) {
                            this.deferredImportSelectors.add(
                                    new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector));
                        }
                        else {
                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                            Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
                            processImports(configClass, currentSourceClass, importSourceClasses, false);
                        }
                    }
                    else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                    //判断如果被import的是 ImportBeanDefinitionRegistrar 接口的实现, 那么初始化后将对当前对象的处理委托给这个ImportBeanDefinitionRegistrar 
                        // 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 {
                    //当做@Configuration配置类去处理,将该类放入 this.importStack栈中,processConfigurationClass方法去递归解析
                        // 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();
            }
        }
    }

关于import注解的这几个类型的使用参考:Spring Import注解

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值