Spring 学习笔记-@Import 注解

@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 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 classNameList = new ArrayList<>();
            // 获取引用到该 ImportSelector 的注解
            Set 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 beanFactoryPostProcessors) {

    Set processedBeans = new HashSet<>();

    if (beanFactory instanceof BeanDefinitionRegistry registry) {
        // 存储所有 BeanFactoryPostProcessor
        List regularPostProcessors = new ArrayList<>();
        // 存储所有 BeanDefinitionRegistryPostProcessor
        List registryProcessors = new ArrayList<>();
        //忽略中间代码
        // 存储当前已经获取到的 BeanDefinitionRegistryPostProcessor
        List 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 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 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 candidates = new LinkedHashSet<>(configCandidates);
    Set 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 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 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 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 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 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 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 readerClass = importResource.getClass("reader");
        for (String resource : resources) {
            String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
            configClass.addImportedResource(resolvedResource, readerClass);
        }
    }

    // 解析 @Bean 方法
    Set 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 importCandidates, Predicate 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 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 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 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 registrars) {
    registrars.forEach((registrar, metadata) ->
            // 调用 ImportBeanDefinitionRegistrars#registerBeanDefinitions() 方法
            registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
}

你可能感兴趣的:(Spring 学习笔记-@Import 注解)