Import 注解与 ImportSelector 和 ImportBeanDefinitionRegistrar

@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的调用细节我们后面再说.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。