Spring注解驱动开发第10讲——在@Import注解中使用ImportBeanDefinitionRegistrar向容器中注册bean
写在前面
在前面的文章中,我们学习了如何使用@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相关推荐
- Spring注解驱动开发第26讲——总有人让我给他讲讲@EnableAspectJAutoProxy注解
@EnableAspectJAutoProxy注解 在配置类上添加@EnableAspectJAutoProxy注解,便能够开启注解版的AOP功能.也就是说,如果要使注解版的AOP功能起作用的话,那么 ...
- Spring注解驱动开发第11讲——面试官让我说说:如何使用FactoryBean向Spring容器中注册bean?
写在前面 经过前面的学习,我们知道可以通过多种方式向Spring容器中注册bean.可以使用@Configuration注解结合@Bean注解向Spring容器中注册bean:可以按照条件向Sprin ...
- Spring注解驱动开发第7讲——如何按照条件向Spring容器中注册bean?这次我懂了!!
写在前面 当bean是单实例,并且没有设置懒加载时,Spring容器启动时,就会实例化bean,并将bean注册到IOC容器中,以后每次从IOC容器中获取bean时,直接返回IOC容器中的bean,而 ...
- Spring注解驱动开发第53讲——Servlet 3.0与Spring MVC的整合分析
写在前面 在前两讲中,我们说了一下ServletContainerInitializer机制以及如何利用ServletContext向web容器中注册Servlet.Listener以及Filter这 ...
- 【视频分享】尚硅谷Java视频教程_Spring注解驱动开发视频教程
<Spring注解驱动开发>是一套帮助我们深入了解Spring原理机制的教程: 现今SpringBoot.SpringCloud技术非常火热,作为Spring之上的框架,他们大量使用到了S ...
- spring注解驱动开发-10 Servlet3.0
Spring AOP实现 前言 servlet3.0简介 ServletContainerInitializer shared libraries(共享库) / runtimes pluggabili ...
- 【Spring注解驱动开发】二狗子让我给他讲讲@EnableAspectJAutoProxy注解
写在前面 最近,二狗子入职了新公司,新入职的那几天确实有点飘.不过慢慢的,他发现他身边的人各个身怀绝技啊,有Spring源码的贡献者,有Dubbo源码的贡献者,有MyBatis源码的贡献者,还有研究A ...
- spring注解驱动开发-8 Spring 扩展原理
Spring 扩展原理 前言 BeanFactoryPostProcessor 测试实例编写 ExtConfig MyBeanFactoryPostProcessor ExtTest 源码分析 Bea ...
- spring注解驱动开发-7 Spring声明式事务
Spring 声明式事务 前言 @EnableTransactionManagement AutoProxyRegistrar InfrastructureAdvisorAutoProxyCreato ...
最新文章
- 在线作图|如何绘制一张山脊图
- 如何在单页应用程序Angular 7中使用FastReport Core Web报表
- SqlServer中怎样从Excel中导入数据
- 2009年岁末年总结
- GCC-windows的预编译版本——nuwen MinGW
- Unity3D入门(二):碰撞检測
- 转-Linux启动过程详解(inittab、rc.sysinit、rcX.d、rc.local)
- php类似indexof的方法[转]
- com.github.pagehelper.PageHelper cannot be cast to org.apache.ibatis.plugin.Interceptor和oracle不识别
- matlab仿真软件 R2017a版本下载
- RabbitMQ整合SpringCloud
- 基于Java语言的51单片机串口通讯PC机程序
- 李嘉诚的语录,经典名人名言-李嘉诚
- 哥大创建了世界上第一个医用毒液数据库
- 设计模式【5】-- 原型模式
- 仓储控制系统(WCS)设计
- Java+webdriver的自动化测试框架搭建
- mysql基于springboot的家政系统毕业设计源码201524
- TDengine中超级表的TAG管理
- java 实现atof函数
热门文章
- 驱动LSM6DS3TR-C实现高效运动检测与数据采集(2)----配置滤波器
- 创建docker swarm集群的时候,docker swarm join --token 会报错,成功解决!!!
- 蓝天白云网站404页面源码
- springBoot实验填报系统
- 华为OD机试真题 Python 实现【九宫格游戏 / 三阶积幻方】【2022 Q4 | 200分】
- Python_OOP1
- 推荐一本前端学习的好书-《2天驾驭DIV+CSS》
- 社群经济与组织社群化 (2)
- 浙江大学计算机科学专业复试考试内容
- 在使用计算机时 若直接通过断点,计算机等级考试三级PC技术练习题汇总(共6章)...