关于java:Spring-学习笔记Import-注解

35次阅读

共计 21568 个字符,预计需要花费 54 分钟才能阅读完成。

@Import 是一个能让类生成为 Spring Bean 的注解。
@Import 注解它次要是配合 ImportSelector 和 @ImportBeanDefinitionRegistrar 的子类,或者一般的 Java Bean 类应用。

@Import 注解源码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
    /**
     * 须要引入的类,通常是 @ImportSelector , @ImportBeanDefinitionRegistrar 的子类;或者是当成其余一般的 Bean 来应用。*/
    Class<?>[] value();
}

一般 Bean 用法

在 @Import 注解导入一般 Bean 时,这个一般 Bean 必须要有无参构造方法,不然的话会报错。

例子

@SpringBootTest
@Import(ImportNormalBeanTest.NormalBeanClass.class)
public class ImportNormalBeanTest {
    @Autowired
    ApplicationContext ctx;

    @Test
    void testNormalBean(){NormalBeanClass bean = ctx.getBean(NormalBeanClass.class);
        System.out.println(bean);
    }

    public static class NormalBeanClass{
        @Override
        public String toString() {return "normal bean";}
    }
}

测试后果

normal bean

ImportSelector

ImportSelector 接口通过自定义的算法,去抉择要引入的 Spring Bean。如果 ImportSelector 的子类实现了以下的接口,它会依照接口的程序先调用这些接口的办法,再去调用 ImportSelector 的办法:

  1. BeanClassLoaderAware
  2. BeanFactoryAware
  3. EnvironmentAware
  4. ResourceLoaderAware

ImportSelector 源码

public interface ImportSelector {// 返回要加载的 class 全限定名,能够通过 Class.getName() 来获取
    String[] selectImports(AnnotationMetadata importingClassMetadata);

    // 是否过滤掉该 ImportSelector 
    // Predicate 返回 true 示意过滤掉,false 或者 null 示意不过滤
    @Nullable
    default Predicate<String> getExclusionFilter() {return null;}

}

例子

@SpringBootTest
@Import(ImportSelectorTest.TestBeanImportSelector.class)
public class ImportSelectorTest {
    @Autowired
    private ApplicationContext ctx;

    @Test
    void test(){final TestBeanClass bean = ctx.getBean(TestBeanClass.class);
        System.out.println(bean);
    }

    // 自定义一个 ImportSelector , 并且实现了 4 个 aware 的接口,用于验证调用程序
    public static class TestBeanImportSelector implements ImportSelector,
            EnvironmentAware, BeanFactoryAware, BeanClassLoaderAware, ResourceLoaderAware {
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {System.out.println("invoke selectImports method");
            return new String[]{TestBeanClass.class.getName()};
        }

        @Override
        public void setBeanClassLoader(ClassLoader classLoader) {System.out.println("BeanClassLoader set");
        }

        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("beanFactory set");
        }

        @Override
        public void setEnvironment(Environment environment) {System.out.println("environment set");
        }

        @Override
        public void setResourceLoader(ResourceLoader resourceLoader) {System.out.println("resourceLoader set");
        }
    }

    public static class TestBeanClass{
        @Override
        public String toString() {return "test bean";}
    }
}

运行后果

BeanClassLoader set
beanFactory set
environment set
resourceLoader set
invoke selectImports method
test bean

配合自定义注解应用

ImportSelector 还能配合自定义注解,来决定须要引入的 Bean。

例子

/**
 * 这里同时引入 TestBeanClassAnnotation 和 AnotherTestBeanClassAnnotation 这 2 个注解
 * 那么会将 TestBeanClass 和 AnotherTestBeanClass 对应的 Bean 加到到 Spring 容器中去
 * 能够只应用其中一个注解,以只加载注解关联的 Bean
 */
@SpringBootTest
@ImportSelectorTest.TestBeanClassAnnotation
@ImportSelectorTest.AnotherTestBeanClassAnnotation
public class ImportSelectorTest {
    @Autowired
    private ApplicationContext ctx;

    @Test
    void test(){System.out.println(ctx.getBean(TestBeanClass.class));
        System.out.println(ctx.getBean(AnotherTestBeanClass.class));
    }

    /**
     * 示意只引入 TestBeanClass 的 Bean
     * 并且通过 @Import 注解来引入 TestBeanImportSelector
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Target(ElementType.TYPE)
    @Import(ImportSelectorTest.TestBeanImportSelector.class)
    public @interface TestBeanClassAnnotation{ }

    /**
     * 示意只引入 AnotherTestBeanClass 的 Bean
     * 并且通过 @Import 注解来引入 TestBeanImportSelector
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Target(ElementType.TYPE)
    @Import(ImportSelectorTest.TestBeanImportSelector.class)
    public @interface AnotherTestBeanClassAnnotation{ }

    // 自定义一个 ImportSelector , 并且实现了 4 个 aware 的接口,用于验证调用程序
    public static class TestBeanImportSelector implements ImportSelector,
            EnvironmentAware, BeanFactoryAware, BeanClassLoaderAware, ResourceLoaderAware {
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {System.out.println("invoke selectImports method");
            List<String> classNameList = new ArrayList<>();
            // 获取援用到该 ImportSelector 的注解
            Set<String> annotationTypes = importingClassMetadata.getAnnotationTypes();
            for (String annotationType : annotationTypes) {if(TestBeanClassAnnotation.class.getName().equals(annotationType)){classNameList.add(TestBeanClass.class.getName());
                }else if(AnotherTestBeanClassAnnotation.class.getName().equals(annotationType)){classNameList.add(AnotherTestBeanClass.class.getName());
                }
            }
            return classNameList.toArray(new String[0]);
        }

        @Override
        public void setBeanClassLoader(ClassLoader classLoader) {System.out.println("BeanClassLoader set");
        }

        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("beanFactory set");
        }

        @Override
        public void setEnvironment(Environment environment) {System.out.println("environment set");
        }

        @Override
        public void setResourceLoader(ResourceLoader resourceLoader) {System.out.println("resourceLoader set");
        }
    }

    // 要应用到的 Bean 对应的 class 
    public static class TestBeanClass{
        @Override
        public String toString() {return "test bean";}
    }

    public static class AnotherTestBeanClass{
        @Override
        public String toString(){return "another test bean";}
    }
}

输入后果

BeanClassLoader set
beanFactory set
environment set
resourceLoader set
invoke selectImports method
test bean
another test bean

ImportBeanDefinitionRegistrar

ImportBeanDefinitionRegistrar 接口适宜应用在创立 BeanDefinition 的场景,例如 Mybatis-Spring 的 MapperScannerRegistrar ,
就是实现了 ImportBeanDefinitionRegistrar 的 registerBeanDefinitions 办法,来注入 Mapper 接口对应的 BeanDefinition。
ImportBeanDefinitionRegistrar 和 ImportSelector 一样,如果 ImportBeanDefinitionRegistrar 的子类也实现了指定的 Aware 子类,也会依照以下程序来执行:

  1. BeanClassLoaderAware
  2. BeanFactoryAware
  3. EnvironmentAware
  4. ResourceLoaderAware

ImportBeanDefinitionRegistrar 源码

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

    // 利用 BeanDefinitionRegistry 来注册 BeanDefinition,后续 Spring 容器通过 BeanDefinition 来创立 Bean
    default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {}}

例子

@SpringBootTest
@Import(ImportBeanDefinitionRegistrarTest.TestImportBeanDefinitionRegistrar.class)
public class ImportBeanDefinitionRegistrarTest {
    @Autowired
    private ApplicationContext ctx;

    @Test
    void test(){System.out.println(ctx.getBean(TestBean.class));
    }

    public static class TestImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            // 增加 TestBean 对应的 BeanDefinition 到 BeanDefinitionRegistry 中
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(TestBean.class);
            AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
            registry.registerBeanDefinition("testBean", beanDefinition);
        }
    }

    public static class TestBean{
        @Override
        public String toString() {return "test bean";}
    }
}

输入后果

test bean

源码解析

在 Spring 初始化容器时,会调用到 AbstractApplicationContext#refresh() 的办法:

AbstractApplicationContext#refresh() 办法

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
            prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            prepareBeanFactory(beanFactory);
        try {postProcessBeanFactory(beanFactory);
            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            // 调用所有注册到的 BeanFactoryPostProcessor 
            invokeBeanFactoryPostProcessors(beanFactory);
            // 疏忽前面局部的代码
        }
        // 疏忽前面局部的代码
    }
}

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 实际上调用以下办法来调用所有 BeanFactoryPostProcessor 
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    // 疏忽以下办法   
}

从下面的源码得悉,实际上调用 PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors() 办法。

PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors() 办法

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {Set<String> processedBeans = new HashSet<>();

    if (beanFactory instanceof BeanDefinitionRegistry registry) {
        // 存储所有 BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        // 存储所有 BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
        // 疏忽中间代码
        // 存储以后曾经获取到的 BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        // 扫描 Beanfactory 曾经加载到的 BeanDefinitionRegistryPostProcessor 的 bean
        // 其中会扫描到一个 ConfigurationClassPostProcessor 的 Bean , 它实现了 BeanDefinitionRegistryPostProcessor 接口
        // 这个 Bean 通过重写 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry() 的办法去做解决 @Import 注解的逻辑
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        // 这里会调用曾经获取到的 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry() 办法,其中曾经蕴含 ConfingurationClassPostProcssor
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
        // 疏忽中间代码
    }
    // 疏忽后续代码
}

// 遍历地调用 postProcessors 参数列表的 postProcessBeanDefinitionRegistry() 办法
private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
                .tag("postProcessor", postProcessor::toString);
        // 循环调用 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry() 办法
        postProcessor.postProcessBeanDefinitionRegistry(registry);
        postProcessBeanDefRegistry.end();}
}

PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors() 中,Spring 加载了 ConfigurationClassPostProcessor 的 Bean 进去。
因为 ConfigurationClassPostProcessor 是 BeanDefinitionRegistryPostProcessor 的子类,故在 invokeBeanDefinitionRegistryPostProcessors 办法中便会调用到
ConfingurationClassPostProcssor#postProcessBeanDefinitionRegistry() 的办法。

ConfingurationClassPostProcssor#postProcessBeanDefinitionRegistry() 办法

// 这里只展现外围的 postProcessBeanDefinitionRegistry() 办法
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    // 疏忽下面局部的代码
    // ConfigurationClassPostProcessor 实际上是调用 processConfigBeanDefinitions() 办法来做具体的逻辑
    processConfigBeanDefinitions(registry);
}

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    // 从 BeanDefinitionRegistry 中获取 BeanDefinitionNames 列表
    String[] candidateNames = registry.getBeanDefinitionNames();
    // 增加 BeanDefinitionNames 列表到 configCandidates 类表中去
    for (String beanName : candidateNames) {BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {if (logger.isDebugEnabled()) {logger.debug("Bean definition has already been processed as a configuration class:" + beanDef);
            }
        }
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }
    // 如果 configCandidates 列表为空,则完结流程
    if (configCandidates.isEmpty()) {return;}
    
    // 如果 BeanDefinition 关联的 class 有 @Order 注解的话,就去排序
    configCandidates.sort((bd1, bd2) -> {int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        return Integer.compare(i1, i2);
    });

    // Detect any custom bean name generation strategy supplied through the enclosing application context
    SingletonBeanRegistry sbr = null;
    if (registry instanceof SingletonBeanRegistry) {sbr = (SingletonBeanRegistry) registry;
        if (!this.localBeanNameGeneratorSet) {BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
            if (generator != null) {
                this.componentScanBeanNameGenerator = generator;
                this.importBeanNameGenerator = generator;
            }
        }
    }

    if (this.environment == null) {this.environment = new StandardEnvironment();
    }

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

    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    do {StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
        // 解析 @Import 注解的入口,并将读取到的类增加到 parser.configurationClasses 列表中
        parser.parse(candidates);
        parser.validate();
        // 读取 parser.configurationClasses.keySet()
        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        // 去掉曾经加载过的 configClasses
        configClasses.removeAll(alreadyParsed);

        if (this.reader == null) {
            this.reader = new ConfigurationClassBeanDefinitionReader(
                    registry, this.sourceExtractor, this.resourceLoader, this.environment,
                    this.importBeanNameGenerator, parser.getImportRegistry());
        }
        // 将 configClasses 转换成 BeanDefinition , 供应前面创立 Bean 的应用
        this.reader.loadBeanDefinitions(configClasses);
        alreadyParsed.addAll(configClasses);
        // 疏忽后续局部代码
    }
    while (!candidates.isEmpty());
    // 疏忽后续局部代码
}

ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry() 办法实际上是调用了 processConfigBeanDefinitions 办法。他次要做了这些事件:

  1. processConfigBeanDefinitions 先去扫描 BeanDefinitionRegistry 保护的 BeanDefinitionNames 列表
  2. 通过 BeanDefinitionNames 列表转换成 configCandidates 列表
  3. configCandidates 列表的元素做排序操作
  4. 通过 ConfigurationClassParser#parse() 办法,去读取 configCandidates 列表, 并将 configCandidates 列表中有应用到的 @Import 注解的类,调用它们相干的办法。
    例如 ImportSelector#selectImports() 办法
    并且将调用办法后失去的后果,存入到 ConfigurationClassParser.configurationClasses 的 map 中去
  5. 调用 ConfigurationClassBeanDefinitionReader#loadBeanDefinitions 办法,将 ConfigurationClassParser.configurationClasses 的 map 内容转换成 BeanDefinition 列表

从下面的流程中,ConfigurationClassParser#parse() 是读取 @Import 注解的要害入口。

ConfigurationClassParser#parse() 办法

public void parse(Set<BeanDefinitionHolder> configCandidates) {for (BeanDefinitionHolder holder : configCandidates) {BeanDefinition bd = holder.getBeanDefinition();
        try {// 这里次要是调用了 parse() 办法
            if (bd instanceof AnnotatedBeanDefinition) {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());
            }
        }
        // 疏忽上面的代码
    }
    this.deferredImportSelectorHandler.process();}

protected final void parse(Class<?> clazz, String beanName) throws IOException {// parse() 办法调用了 processConfigurationClass() 办法
    processConfigurationClass(new ConfigurationClass(clazz, beanName), DEFAULT_EXCLUSION_FILTER);
}

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
    // 疏忽下面局部的代码
    SourceClass sourceClass = asSourceClass(configClass, filter);
    do {// 次要是调用 doProcessConfigurationClass() 办法 
        sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
    }
    while (sourceClass != null);
    // 将 doProcessConfigurationClass() 办法批改的 configClass 塞到 configurationClasses 的 Map 中去
    this.configurationClasses.put(configClass, configClass);
}

protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
        throws IOException {if (configClass.getMetadata().isAnnotated(Component.class.getName())) {// Recursively process any member (nested) classes first
        processMemberClasses(configClass, sourceClass, filter);
    }

    // 解析 @PropertySource 的注解
    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class,
            org.springframework.context.annotation.PropertySource.class)) {if (this.propertySourceRegistry != null) {this.propertySourceRegistry.processPropertySource(propertySource);
        }
        else {logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                    "]. Reason: Environment must implement ConfigurableEnvironment");
        }
    }

    // 解析 @ComponentScan 的注解 
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    if (!componentScans.isEmpty() &&
            !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {for (AnnotationAttributes componentScan : componentScans) {
            // The config class is annotated with @ComponentScan -> perform the scan immediately
            Set<BeanDefinitionHolder> scannedBeanDefinitions =
                    this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
            // Check the set of scanned definitions for any further config classes and parse recursively if needed
            for (BeanDefinitionHolder holder : scannedBeanDefinitions) {BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                if (bdCand == null) {bdCand = holder.getBeanDefinition();
                }
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {parse(bdCand.getBeanClassName(), holder.getBeanName());
                }
            }
        }
    }

    // 解析 @Import 注解
    processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

    // 解析 @ImportResource 注解
    AnnotationAttributes importResource =
            AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    if (importResource != null) {String[] resources = importResource.getStringArray("locations");
        Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
        for (String resource : resources) {String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
            configClass.addImportedResource(resolvedResource, readerClass);
        }
    }

    // 解析 @Bean 办法
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }

    // 疏忽上面的办法
}

从下面的代码执行流程中,能够看到解析 @Import 注解的是 ConfigurationClassParser#processImports() 办法

ConfigurationClassParser#processImports() 办法

该办法时解析 @Import 注解的外围逻辑:

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
        Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
        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 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() 办法,获取 Bean 对应的 class 名字
                        String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                        Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                        // 将这些获取到的 class 名字递归地调用 processImports() 办法
                        processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, 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 =
                            ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
                                    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), exclusionFilter);
                }
            }
        }
        catch (BeanDefinitionStoreException ex) {throw ex;}
        catch (Throwable ex) {
            throw new BeanDefinitionStoreException(
                    "Failed to process import candidates for configuration class [" +
                    configClass.getMetadata().getClassName() + "]:" + ex.getMessage(), ex);
        }
        finally {this.importStack.pop();
        }
    }
}

ConfigurationClassBeanDefinitionReader#loadBeanDefinitions() 办法

当 Spring 加载完了 @Import 注解之后,会通过 ConfigurationClassBeanDefinitionReader#loadBeanDefinitions() 办法来调用
ImportBeanDefinitionRegistrar#registerBeanDefinitions() 办法。

ImportBeanDefinitionRegistrar#registerBeanDefinitions() 办法就是 ImportBeanDefinitionRegistrar 的实现类要实现的办法。

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    for (ConfigurationClass configClass : configurationModel) {loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    }
}

private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
    // 疏忽下面的代码
    // 这里就是调用 ImportBeanDefinitionRegistrars#registerBeanDefinitions() 办法的入口
    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {registrars.forEach((registrar, metadata) ->
            // 调用 ImportBeanDefinitionRegistrars#registerBeanDefinitions() 办法
            registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
}

正文完
 0