首页 > 其他分享 >@Import注解详解

@Import注解详解

时间:2023-01-05 18:13:07浏览次数:66  
标签:configClass ImportBeanDefinitionRegistrar class ImportSelector 详解 注解 Import publ

@Import注解详解

1.原文链接:https://blog.csdn.net/weixin_45453628/article/details/124234317

2. AnnotationConfigApplicationContext容器创建过程

https://www.cnblogs.com/ashleyboy/p/9662119.html

____________________________________________________________________________________________________________________________________________________________

 

@Import注解提供了三种用法

1、@Import一个普通类 spring会将该类加载到spring容器中

2、@Import一个类,该类实现了ImportBeanDefinitionRegistrar接口,在重写的registerBeanDefinitions方法里面,能拿到BeanDefinitionRegistry bd的注册器,能手工往beanDefinitionMap中注册 beanDefinition

3、@Import一个类 该类实现了ImportSelector 重写selectImports方法该方法返回了String[]数组的对象,数组里面的类都会注入到spring容器当中

 

接下来挨个测试:

场景一 import普通类

1. 自定义一个类 没有任何注解

public class MyClass {
  public void test() {
    System.out.println("test方法");
  }
}

 

2. 写一个importConfig类 import这个myClass类

@Import(MyClass.class)
public class ImportConfig {
}

 


3. 通过AnnotationConfigApplicationContext 初始化spring容器 调用test方法 看输出, MyClass类被加载进了 spring容器当中

 

 

 

场景二、 实现ImportBeanDefinitionRegistrar

 1. 创建一个普通类MyClassRegistry

public class MyClassRegistry {
    
    public void test() {
        System.out.println("MyClassRegistry test方法");
    }
}

 

2. 创建MyImportRegistry 实现ImportBeanDefinitionRegistrar接口 注册我们定义的普通类MyClassRegistry

public class MyImportRegistry implements ImportBeanDefinitionRegistrar{
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition bd = new RootBeanDefinition();
        bd.setBeanClass(MyClassRegistry.class);
        registry.registerBeanDefinition("myClassRegistry", bd);
    }
}

 3. import该类

@Import(MyImportRegistry.class)
public class ImportConfig {    
}

 

4. 执行main方法 查看输出

 

 

 

场景三、 实现ImportSelector

1. 创建一个普通类MyClassImport

public class MyClassImport {
    public void test() {
        System.out.println("MyClassImport test方法");
    }
}

2. 创建MyImportSelector实现ImportSelector接口 注册我们定义的普通类MyClassImport

public class MyImportSelector implements ImportSelector {
  @Override
  public String[] selectImports(AnnotationMetadata importingClassMetadata) {
    return new String[] {MyClassImport.class.getName()};
  }
}

3. import该类

@Import(MyImportSelector.class)
public class ImportConfig {
}

 

4. 执行main方法 查看输出

 

 

场景二应用于spring-mybatis当中 扫描dao信息 生成代理类信息

场景三应用于springboot的自动装配当中 加载自动装配需要的类信息 

源码分析:

org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClass, SourceClass, Collection<SourceClass>, boolean)方法中 就是处理Import注解类引入的bd信息

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass, Collection<SourceClass> importCandidates, 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) {
                    if (candidate.isAssignable(ImportSelector.class)) {//拿ImportSelector类
                    
                        Class<?> candidateClass = candidate.loadClass();//获得class信息
                        ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
                                this.environment, this.resourceLoader, this.registry);
                        if (selector instanceof DeferredImportSelector) {//判断是否是延迟加载的ImportSelector对象
                            this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
                        }
                        else {
                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());//拿到selectImports方法返回的类信息
                            Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
                            processImports(configClass, currentSourceClass, importSourceClasses, false);
                        }
                    }
                    else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {//扫描到类是继承ImportBeanDefinitionRegistrar 将配置类封装成ConfigurationClass类 后续会处理
                        // 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());
                    }
                    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));
                    }
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                        "Failed to process import candidates for configuration class [" +
                        configClass.getMetadata().getClassName() + "]", ex);
            }
            finally {
                this.importStack.pop();
            }
        }
    }

 

org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(Set<ConfigurationClass>)

在loadBeanDefinitions中会调用loadBeanDefinitionsFromRegistrars方法 最终执行到实现类的registerBeanDefinitions方法 继而将自定义的bd注册到beanDefinitionMap当中 交给spring去初始化。

 

标签:configClass,ImportBeanDefinitionRegistrar,class,ImportSelector,详解,注解,Import,publ
From: https://www.cnblogs.com/kelelipeng/p/17028505.html

相关文章

  • 反射5 - 获取注解信息
    反射获取注解信息什么是ORM?ObjectrelationshipMapping--对象关系映射(数据库关系)类->表类中属性->表的字段类的对象->表中的记录通过注解联系属性与数据......
  • Cocos2d-x windows + vs2010 配置图文详解
    参考:​​http://tieba.baidu.com/p/1461284351​​ 1.下载最新版的cocos2d-x。打开浏览器,输入cocos2d-x.org,然后选择Download,本教程写作时最新版本为cocos2d-1.01-x-0.9.1,......
  • 注解2 - 元注解
    元注解meta-annotation注解其他注解这些类型和它们所支持的类在java.lang.annotation包中找到@Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)@Retent......
  • Java Annotation-注解
    Java注解(Annotation)是JDK5.0引入的一种注释机制。Java语言中的类、方法、变量、参数和包等都可以被注解。和Javadoc不同,Java注解可以通过反射获取标注内容。在编译器生成......
  • GPIO详解
    本文以STM32F40为例进行讲解,其它雷同1.GPIO简介GPIO(generalpurposeinputoutput,通用输入输出端口)简单来说就是软件可控制的引脚:STM32芯片的GPIO引脚与外部设备连接......
  • Retrofit用法详解
    一、基础介绍1、定义Java形式的HTTPAPI接口publicinterfaceBlueService{@GET("book/search")Call<BookSearchResponse>getSearchBooks(@Query("q")Stringname,......
  • 安装算量软件安装流程详解
    安装算量软件安装流程1.以管理员身份运行安装包2.点击安装(注:如此时杀毒软件提示阻止,一律点允许)3.按如图所示点击下一步4.软件安装路劲建议不要装C盘,把路径改为D盘或其他......
  • 【Nginx基础知识】详解nginx配置url重定向-反向代理
    【Nginx基础知识】详解nginx配置url重定向-反向代理本文系统:Centos6.5_x64三台主机:nginx主机,hostname:master.lansgg.com IP:192.168.10.128           ......
  • linux crontab 定时任务详解
    前言正如闹钟对于日常生活的重要性一样,linuxcrontab定时任务在开发中是必不可少的工具,诸如:每六个月清理一次日志,每天凌晨12.00重启服务等多种场景,都可以用crontab......
  • webpack 中import 引入umd模块module
    在webpack项目中引入一个umd模块,如果你的项目是由create-react-app搭建的,很大概率会遇到importerror。这很大概率是由于babel-loader重复编译导致的,因为umd模块一般是经......