• 解析@Import底层原理


    目录

    一、概述

     二、底层解析

    1、ConfigurationClassPostProcessor

    2、ConfigurationClassParser

     3、doProcessConfigurationClass

     4、processImports

    4.1 ImportSelector

     4.2 ImportBeanDefinitionRegistrar

      4.3 普通组件类

     三、测试类


    一、概述

    @Import用来向ioc容器注册组件。

    注意:@Import只是向容器注册添加组件的相关信息,组件还未实例化,后续由容器进行实例化。

    value数组值:

    普通组件类、实现ImportSelector接口的实现类、实现ImportBeanDefinitionRegistrar接口的实现类

    1、普通组件类:直接向容器注册组件,组件的id为组件的全限定类名,若是组件是一个配置类,则配置类内的组件(若配置类定义了内部类,也会扫描内部类判断是否加载该内部类)也会被注册到容器中

    2、实现ImportSelector接口的实现类:通过实现selectImports方法返回组件的全限定类名数组,组件的id为组件的全限定类名

    1. public class MyImportSelector implements ImportSelector {
    2. /**
    3. *
    4. * @param importingClassMetadata 当前标识Import注解的类的所有注解信息
    5. * @return 返回组件的全类名
    6. */
    7. @Override
    8. public String[] selectImports(AnnotationMetadata importingClassMetadata) {
    9. return new String[]{"com.mzp.component.service.Red"};
    10. }
    11. }

    3、实现ImportBeanDefinitionRegistrar接口的实现类:通过实现registerBeanDefinitions方法,可自定义向容器注册组件,可指定组件id

    1. public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    2. /**
    3. *
    4. * @param importingClassMetadata 标识Import注解的类的所有注解信息
    5. * @param registry Bean定义的注册类
    6. */
    7. @Override
    8. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    9. RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainRow.class);
    10. registry.registerBeanDefinition("rain",rootBeanDefinition);
    11. }
    12. }

     二、底层解析

    1、ConfigurationClassPostProcessor

    用来解析标识@Configuration配置类。

    创建ioc容器时将ConfigurationClassPostProcessor注册到容器中,这是一个BeanDefinitionRegistryPostProcessor实现类,refresh方法中运行invokeBeanDefinitionRegistryPostProcessors方法时,调用ConfigurationClassPostProcessorpostProcessBeanDefinitionRegistry方法里的processConfigBeanDefinitions方法去解析容器已注册的标识@Configuration的配置类

     processConfigBeanDefinitions方法创建ConfigurationClassParser对象去解析@Configuration配置类的信息,包括解析注解@Import信息

    2、ConfigurationClassParser

    parse方法中调用processConfigurationClass方法

     processConfigurationClass方法通过循环调用doProcessConfigurationClass方法来解析当前配置类和配置类的父类信息

     3、doProcessConfigurationClass

    doProcessConfigurationClass方法解析多个spring注解,例如

    @PropertySource、@ComponentScan、@Import、@ImportResource、@Bean、解析内部类信息等

    解析内部类

     定位到如图processImports方法,该方法就是实际用来解析@Import注解

     getImports方法返回所有@Import注解的value集合,getImports方法通过collectImports方法获取当前组件标识@Import的value集合,包括元注解内部的@Import的value集合

     4、processImports

    processImports方法中遍历已得到@Import的value集合importCandidates,判断每个value属于哪种类型

    4.1 ImportSelector

    若是value实现了ImportSelector接口,则先通过容器工具类创建对象,然后调用对象的selectImports方法得到导入组件数组importClassNames,继续递归调用processImports方法解析每个导入组件

     4.2 ImportBeanDefinitionRegistrar

    若是value实现了ImportBeanDefinitionRegistrar接口, 创建该对象,将对象添加到当前类的importBeanDefinitionRegistrars集合中

     在后续解析完所有的@Configuration配置类后,调用ConfigurationClassPostProcessorloadBeanDefinitions方法注册每个配置组件类到容器时,

     调用loadBeanDefinitionsForConfigurationClass方法loadBeanDefinitionsFromRegistrars方法运行当前类的importBeanDefinitionRegistrars集合的registerBeanDefinitions方法

      4.3 普通组件类

    当前value都没实现ImportSelectorImportBeanDefinitionRegistrar接口时,将它当成一个配置类继续调用processConfigurationClass方法解析该配置类

     三、测试类

    1. @Test
    2. public void test15(){
    3. ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ImportConfig.class);
    4. }
    1. package com.mzp.component.myimport;
    2. import com.mzp.component.service.RainRow;
    3. import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    4. import org.springframework.beans.factory.support.RootBeanDefinition;
    5. import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
    6. import org.springframework.core.type.AnnotationMetadata;
    7. public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    8. /**
    9. *
    10. * @param importingClassMetadata 标识Import注解的类的所有注解信息
    11. * @param registry Bean定义的注册类
    12. */
    13. @Override
    14. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    15. RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainRow.class);
    16. registry.registerBeanDefinition("rain",rootBeanDefinition);
    17. }
    18. }
    1. package com.mzp.component.myimport;
    2. import org.springframework.context.annotation.ImportSelector;
    3. import org.springframework.core.type.AnnotationMetadata;
    4. public class MyImportSelector implements ImportSelector {
    5. /**
    6. *
    7. * @param importingClassMetadata 当前标识Import注解的类的所有注解信息
    8. * @return 返回组件的全类名
    9. */
    10. @Override
    11. public String[] selectImports(AnnotationMetadata importingClassMetadata) {
    12. return new String[]{"com.mzp.component.service.Red"};
    13. }
    14. }
    1. package com.mzp.component.myimport;
    2. public class Test {
    3. public Test(){
    4. System.out.println("Test()");
    5. }
    6. }
    1. package com.mzp.component.config;
    2. import com.mzp.component.myimport.MyImportBeanDefinitionRegistrar;
    3. import com.mzp.component.myimport.MyImportSelector;
    4. import com.mzp.component.myimport.Test;
    5. import org.springframework.context.annotation.Configuration;
    6. import org.springframework.context.annotation.Import;
    7. @Configuration
    8. @Import(value = {Test.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
    9. public class ImportConfig {
    10. }

  • 相关阅读:
    【Netty】九、Netty自定义协议
    C++ 类型转换
    Automatic Detection of Welding Defects Using Faster R-CNN
    StarGAN v2: Diverse Image Synthesis for Multiple Domains (多域多样性图像合成)
    OPPO的关键一步
    内置AI算法的智能分析网关,如何将智能识别技术应用到生活场景中?
    Java异常处理机制
    Unity --- 网格链接与动态障碍物
    AIGC创作系统ChatGPT网站系统源码,支持最新GPT-4-Turbo模型
    【MATLAB源码-第153期】基于matlab的OFDM系统插入导频和训练符号两种信道估计方式误码率对比仿真。
  • 原文地址:https://blog.csdn.net/weixin_37607613/article/details/126179029