写在前面

在前面的文章中,我们学习了如何使用@Import注解向Spring容器中导入bean,不仅可以使用@Import注解快速向容器中导入bean,也可以在@Import注解中使用ImportSelector接口的方法导入bean,今天,我们就来说说,如何在@Import注解中使用ImportBeanDefinitionRegistrar向容器中注册bean。

ImportBeanDefinitionRegistrar接口的简要介绍

概述

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

由源码可以看出,ImportBeanDefinitionRegistrar本质上是一个接口。在ImportBeanDefinitionRegistrar接口中,有一个registerBeanDefinitions()方法,通过该方法,我们可以向Spring容器中注册bean实例。

Spring官方在动态注册bean时,大部分套路其实是使用ImportBeanDefinitionRegistrar接口。

所有实现了该接口的类都会被ConfigurationClassPostProcessor处理,ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口,所以ImportBeanDefinitionRegistrar中动态注册的bean是优先于依赖其的bean初始化的,也能被aop、validator等机制处理。

使用方法

ImportBeanDefinitionRegistrar需要配合@Configuration和@Import这俩注解,其中,@Configuration注解定义Java格式的Spring配置文件,@Import注解导入实现了ImportBeanDefinitionRegistrar接口的类。

ImportBeanDefinitionRegistrar接口实例

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

package com.meimeixia.condition;import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {/*** AnnotationMetadata:当前类的注解信息* BeanDefinitionRegistry:BeanDefinition注册类* * 我们可以通过调用BeanDefinitionRegistry接口中的registerBeanDefinition方法,手动注册所有需要添加到容器中的bean*/@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {}}

可以看到,这里,我们先创建了MyImportBeanDefinitionRegistrar类的大体框架。然后,我们在MainConfig2配置类上的@Import注解中,添加MyImportBeanDefinitionRegistrar类,如下所示。

package com.meimeixia.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Lazy;import com.meimeixia.bean.Color;
import com.meimeixia.bean.Person;
import com.meimeixia.bean.Red;
import com.meimeixia.condition.LinuxCondition;
import com.meimeixia.condition.MyImportBeanDefinitionRegistrar;
import com.meimeixia.condition.MyImportSelector;
import com.meimeixia.condition.WindowsCondition;// 对配置类中的组件进行统一设置
@Conditional({WindowsCondition.class}) // 满足当前条件,这个类中配置的所有bean注册才能生效
@Configuration
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) // @Import快速地导入组件,id默认是组件的全类名
public class MainConfig2 {@Lazy@Bean("person")public Person person() {System.out.println("给容器中添加咱们这个Person对象...");return new Person("美美侠", 25);}@Bean("bill")public Person person01() {return new Person("Bill Gates", 62);}@Conditional({LinuxCondition.class})@Bean("linus")public Person person02() {return new Person("linus", 48);}}

接着,创建一个RainBow类,作为测试ImportBeanDefinitionRegistrar接口的bean来使用,如下所示。

package com.meimeixia.bean;public class RainBow {}

紧接着,我们就要实现MyImportBeanDefinitionRegistrar类中的registerBeanDefinitions()方法里面的逻辑了,添加逻辑后的registerBeanDefinitions()方法如下所示。

package com.meimeixia.condition;import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;import com.meimeixia.bean.RainBow;public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {/*** AnnotationMetadata:当前类的注解信息* BeanDefinitionRegistry:BeanDefinition注册类* * 我们可以通过调用BeanDefinitionRegistry接口中的registerBeanDefinition方法,手动注册所有需要添加到容器中的bean*/@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {boolean definition = registry.containsBeanDefinition("com.meimeixia.bean.Red");boolean definition2 = registry.containsBeanDefinition("com.meimeixia.bean.Bule");if (definition && definition2) {// 指定bean的定义信息,包括bean的类型、作用域等等// RootBeanDefinition是BeanDefinition接口的一个实现类RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class); // bean的定义信息// 注册一个bean,并且指定bean的名称registry.registerBeanDefinition("rainBow", beanDefinition);}}}

以上registerBeanDefinitions()方法的实现逻辑很简单,就是判断Spring容器中是否同时存在以com.meimeixia.bean.Red命名的bean和以com.meimeixia.bean.Bule命名的bean,如果真的同时存在,那么向Spring容器中注入一个以rainBow命名的bean。

最后,我们运行IOCTest类中的testImport()方法来进行测试,输出结果信息如下所示。

可以看到,此时输出了rainBow,说明Spring容器中已经成功注册了以rainBow命名的bean。

Spring注解驱动开发第10讲——在@Import注解中使用ImportBeanDefinitionRegistrar向容器中注册bean相关推荐

  1. Spring注解驱动开发第26讲——总有人让我给他讲讲@EnableAspectJAutoProxy注解

    @EnableAspectJAutoProxy注解 在配置类上添加@EnableAspectJAutoProxy注解,便能够开启注解版的AOP功能.也就是说,如果要使注解版的AOP功能起作用的话,那么 ...

  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注解驱动开发第53讲——Servlet 3.0与Spring MVC的整合分析

    写在前面 在前两讲中,我们说了一下ServletContainerInitializer机制以及如何利用ServletContext向web容器中注册Servlet.Listener以及Filter这 ...

  5. 【视频分享】尚硅谷Java视频教程_Spring注解驱动开发视频教程

    <Spring注解驱动开发>是一套帮助我们深入了解Spring原理机制的教程: 现今SpringBoot.SpringCloud技术非常火热,作为Spring之上的框架,他们大量使用到了S ...

  6. spring注解驱动开发-10 Servlet3.0

    Spring AOP实现 前言 servlet3.0简介 ServletContainerInitializer shared libraries(共享库) / runtimes pluggabili ...

  7. 【Spring注解驱动开发】二狗子让我给他讲讲@EnableAspectJAutoProxy注解

    写在前面 最近,二狗子入职了新公司,新入职的那几天确实有点飘.不过慢慢的,他发现他身边的人各个身怀绝技啊,有Spring源码的贡献者,有Dubbo源码的贡献者,有MyBatis源码的贡献者,还有研究A ...

  8. spring注解驱动开发-8 Spring 扩展原理

    Spring 扩展原理 前言 BeanFactoryPostProcessor 测试实例编写 ExtConfig MyBeanFactoryPostProcessor ExtTest 源码分析 Bea ...

  9. spring注解驱动开发-7 Spring声明式事务

    Spring 声明式事务 前言 @EnableTransactionManagement AutoProxyRegistrar InfrastructureAdvisorAutoProxyCreato ...

最新文章

  1. 在线作图|如何绘制一张山脊图
  2. 如何在单页应用程序Angular 7中使用FastReport Core Web报表
  3. SqlServer中怎样从Excel中导入数据
  4. 2009年岁末年总结
  5. GCC-windows的预编译版本——nuwen MinGW
  6. Unity3D入门(二):碰撞检測
  7. 转-Linux启动过程详解(inittab、rc.sysinit、rcX.d、rc.local)
  8. php类似indexof的方法[转]
  9. com.github.pagehelper.PageHelper cannot be cast to org.apache.ibatis.plugin.Interceptor和oracle不识别
  10. matlab仿真软件 R2017a版本下载
  11. RabbitMQ整合SpringCloud
  12. 基于Java语言的51单片机串口通讯PC机程序
  13. 李嘉诚的语录,经典名人名言-李嘉诚
  14. 哥大创建了世界上第一个医用毒液数据库
  15. 设计模式【5】-- 原型模式
  16. 仓储控制系统(WCS)设计
  17. Java+webdriver的自动化测试框架搭建
  18. mysql基于springboot的家政系统毕业设计源码201524
  19. TDengine中超级表的TAG管理
  20. java 实现atof函数

热门文章

  1. 驱动LSM6DS3TR-C实现高效运动检测与数据采集(2)----配置滤波器
  2. 创建docker swarm集群的时候,docker swarm join --token 会报错,成功解决!!!
  3. 蓝天白云网站404页面源码
  4. springBoot实验填报系统
  5. 华为OD机试真题 Python 实现【九宫格游戏 / 三阶积幻方】【2022 Q4 | 200分】
  6. Python_OOP1
  7. 推荐一本前端学习的好书-《2天驾驭DIV+CSS》
  8. 社群经济与组织社群化 (2)
  9. 浙江大学计算机科学专业复试考试内容
  10. 在使用计算机时 若直接通过断点,计算机等级考试三级PC技术练习题汇总(共6章)...