美文网首页
Import 注解与 ImportSelector 和 Impo

Import 注解与 ImportSelector 和 Impo

作者: Joker__k | 来源:发表于2019-04-17 17:58 被阅读0次

    @Import注解常出现在@Enable注解里面,上一篇@Enable 注解原理解析里知道@Enable只所以能发生作用,对Spring进行配置主要靠的就是@Import注解

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Import {
    
        /**
         * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
         * or regular component classes to import.
         */
        Class<?>[] value();
    
    }
    

    它的源码很简单,value为一个Class的数组,只要这些Class是加上@Configuration注解,或者实现了ImportSelectorImportBeanDefinitionRegistrar就会自动加载了

    我们简单介绍一下这三种情况

    @Configuration注解我就不说了

    ImportBeanDefinitionRegistrar

    public interface ImportBeanDefinitionRegistrar {
        public void registerBeanDefinitions(
                AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
    }
    

    AnnotationMetadata就是你加上@Import注解的地方
    BeanDefinitionRegistry然后你就可以把你需要的BeanDefinition注册进去

    ImportSelector

    public interface ImportSelector {
        String[] selectImports(AnnotationMetadata importingClassMetadata);
    }
    

    ImportSelector返回一个Class的数组,这些类也可以实现ImportBeanDefinitionRegistrarImportSelector再进行配置,有点递归的赶脚,后面看他的源码实现就是递归

    上面三种情况可以同时满足吗

    答案是否定的

    我们看一下ConfigurationClassParser#processImports

    for (SourceClass candidate : importCandidates) {
        // 如果import的类实现了ImportSelector
        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 (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
                processImports(configClass, currentSourceClass, importSourceClasses, false);
            }
        }
        // 如果import的类实现了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());
        }
        // 都不满足,当做@Configuration来处理
        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));
        }
    }
    

    ImportBeanDefinitionRegistrar的调用细节我们后面再说.

    相关文章

      网友评论

          本文标题:Import 注解与 ImportSelector 和 Impo

          本文链接:https://www.haomeiwen.com/subject/nmncwqtx.html