一、ImportBeanDefinitionRegistrar

我们先来看看ImportBeanDefinitionRegistrar是个什么鬼,点击进入ImportBeanDefinitionRegistrar源码,如下所示。

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

由源码可以看出,ImportBeanDefinitionRegistrar本质上是一个接口。在ImportBeanDefinitionRegistrar接口中,有一个registerBeanDefinitions()方法,通过registerBeanDefinitions()方法,我们可以向Spring容器中注册bean实例。Spring官方在动态注册bean时,大部分套路其实是使用ImportBeanDefinitionRegistrar接口。所有实现了该接口的类都会被ConfigurationClassPostProcessor处理,ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口,进一步实现了BeanDefinitionRegistryPostProcessor。该接口主要功能是参与BeanFactory的建造,主要功能如下: 解析加了@Configuration的配置类 解析@ComponentScan扫描的包 解析@ComponentScans扫描的包,解析@Bean,@Import ,@PreopertySource。所以ImportBeanDefinitionRegistrar中动态注册的bean是优先于依赖其的bean初始化的,也能被aop、validator等机制处理。

  • 实现了ImportBeanDefinitionRegistrar的类,在refresh的invokeBeanFactoryPostProcessors阶段,调用到最后,会调用到registerBeanDefinitios

ImportBeanDefinitionRegistrar调用链

二、使用方法

ImportBeanDefinitionRegistrar需要配合@Import注解,@Import注解导入实现了ImportBeanDefinitionRegistrar接口的类。

  1. ImportBeanDefinitionRegistrar实例

既然ImportBeanDefinitionRegistrar是一个接口,那我们就创建一个MyImportBeanDefinitionRegistrar类,实现ImportBeanDefinitionRegistrar接口,如下所示。

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{/*** AnnotationMetadata: 当前类的注解信息* BeanDefinitionRegistry:BeanDefinition注册类* 通过调用BeanDefinitionRegistry接口的registerBeanDefinition()方法,可以将所有需要添加到容器中的bean注入到容器中。*/@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {boolean dao1= registry.containsBeanDefinition("com.myImportBeanDefinitionRegistrar.MyDao1");boolean dao2= registry.containsBeanDefinition("com.myImportBeanDefinitionRegistrar.MyDao2");if (dao2 && dao1){BeanDefinition beanDefinition = new RootBeanDefinition(MyDao3.class);registry.registerBeanDefinition("myDao3", beanDefinition);}}
}
public class MyDao(1/2/3) {public void query(){System.out.println("query MyDao for MyImportSelect");}
}
@Import({MyDao1.class,MyDao2.class})
@EnableMyImportBeanDefinitionRegistrar
public class AppConfig {}@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MyImportBeanDefinitionRegistrar.class)
public @interface EnableMyImportBeanDefinitionRegistrar {}public class MyTest {public static void main(String[] args) {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);Arrays.stream(ctx.getBeanDefinitionNames()).toList().forEach(System.out::println);}
}

通过EnableMyImportBeanDefinitionRegistrar 注解,我们根据条件判断,动态引入了MyDao3.class

三、大部分框架的套路也如此

  1. openFeign
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {}FeignClientsRegistrar实现了ImportBeanDefinitionRegistrar接口
  1. mybatis
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({MapperScannerRegistrar.class})
@Repeatable(MapperScans.class)
public @interface MapperScan {}MapperScannerRegistrar实现了ImportBeanDefinitionRegistrar接口
  1. 也有的是实现importSelector接口,通过返回一个包含类名的数组进行注入的

参考文章

ImportBeanDefinitionRegistrar向容器中注册bean相关推荐

  1. Spring注解驱动开发第10讲——在@Import注解中使用ImportBeanDefinitionRegistrar向容器中注册bean

    写在前面 在前面的文章中,我们学习了如何使用@Import注解向Spring容器中导入bean,不仅可以使用@Import注解快速向容器中导入bean,也可以在@Import注解中使用ImportSe ...

  2. Spring注解驱动开发第11讲——面试官让我说说:如何使用FactoryBean向Spring容器中注册bean?

    写在前面 经过前面的学习,我们知道可以通过多种方式向Spring容器中注册bean.可以使用@Configuration注解结合@Bean注解向Spring容器中注册bean:可以按照条件向Sprin ...

  3. Spring注解驱动开发第7讲——如何按照条件向Spring容器中注册bean?这次我懂了!!

    写在前面 当bean是单实例,并且没有设置懒加载时,Spring容器启动时,就会实例化bean,并将bean注册到IOC容器中,以后每次从IOC容器中获取bean时,直接返回IOC容器中的bean,而 ...

  4. 【小家Spring】Spring注解驱动开发---向Spring Ioc容器中注册Bean的7种方式

    每篇一句 比你有钱的人一定会比你努力,而比你努力的人终有一天会比你有钱 前言 Spring是一个非常强大的反转控制(IOC)框架,以帮助分离项目组件之间的依赖关系.因此可以说Spring容器对Bean ...

  5. 给容器中注册组件 || @Scope -- @Lazy -- @Conditional({Condition}) -- @Import--使用Spring提供的 FactoryBean

    * @Scope:调整作用域    * prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中.       *              每次获取的时候才会调用方法创建对象: ...

  6. @EnableAspectJAutoProxy||AOP原理:【看给容器中注册了什么组件,这个组件什么时候工作,这个组件的功能是什么?】

    AOP原理:[看给容器中注册了什么组件,这个组件什么时候工作,这个组件的功能是什么?] @EnableAspectJAutoProxy是什么? * AOP原理:[看给容器中注册了什么组件,这个组件什么 ...

  7. 2、组件注册-@Configuration@Bean给容器中注册组件

    2.组件注册-@Configuration&@Bean给容器中注册组件 2.1 创建maven项目 spring-annotation pom.xml文件添加 spring-context 依 ...

  8. Spring容器中的Bean是否会被GC呢?

    Spring容器中的Bean是否会被GC呢?最近好几次被校招实习生问及,对于初学者来说,这应该是一个有意思的问题,鉴于此,笔者顺便写个这个文档. 1.Spring容器中Bean的作用域 当通过Spri ...

  9. FastJson序列化Json自定义返回字段,普通类从spring容器中获取bean

    前言: 数据库的字段比如:price:1 ,返回需要price:1元. 这时两种途径修改: ① 比如sql中修改或者是在实体类转json前遍历修改. ②返回json,序列化时候修改.用到的是fastj ...

最新文章

  1. 统计学习II.7 广义线性模型1 指数分布族
  2. FreeRTOS的中断优先级配置小结
  3. mysql 导致iis 假死_解决IIS无响应假死状态
  4. 又一低代码平台火了!15 分钟小白轻松开发在线课堂,人人都是开发者时代来了?
  5. 前端数据库——WebSQL和IndexedDB
  6. ORA-14402: 更新分区关键字导致分区的更改
  7. nginx 配置路由
  8. 力扣-面试题 02.06. 回文链表
  9. SQL Sever数据库的基本操作和它的建立
  10. 管理新语:别人反映问题,你要形成自己的材料
  11. Android入门基础教程(小白速成1)
  12. Robo 3T下载安装和使用
  13. Java mail 接受网易126和163邮件时数目不全
  14. 2016年中南大学校赛镜像赛(校外队伍)
  15. IBM小型机更换硬盘详细步骤
  16. 由浅入深的分析HashMap原理
  17. 各种类型sizeof大小及C++有符号数与无符号数进行比较
  18. 自训练和协同训练简述
  19. if+switch 循环
  20. HDRP打包后材质黑色问题

热门文章

  1. 4.SELECT DISTINCT 语句
  2. linux系统进程的内存布局
  3. (转)工作了一个星期各位一定累了吧,那我们一起来表单验证一番吧!
  4. WCF揭秘学习笔记(5):WF定制活动
  5. 单核工作法17:简化协作(上)
  6. 统计学习:方差分析(ANOVA2)
  7. c运行库、c标准库、windows API都是什么玩意
  8. keras多输出模型
  9. 【随笔】通用近似定理
  10. [云炬创业学笔记]第一章创业是什么测试5