Spring学习之ImportBeanDefinitionRegistrar接口
一、本文内容分类
1、接口功能
2、接口运用场景
3、使用案例
4、注意事项
二、接口功能介绍
描述:ImportBeanDefinitionRegistrar接口是也是spring的扩展点之一,它可以支持我们自己写的代码封装成BeanDefinition对象,注册到Spring容器中,功能类似于注解@Service @Component。
很多三方框架集成Spring的时候,都会通过该接口,实现扫描指定的类,然后注册到spring容器中,比如Mybatis中的Mapper接口,springCloud中的FeignClient接口,都是通过该接口实现的自定义注册逻辑。
1、ImportBeanDefinitionRegistrar接口实现类,只能通过@Import注解的方式来注入,通常把@Import修饰在启动类或配置类。
2、使用@Import,如果括号中的类是ImportBeanDefinitionRegistrar的实现类,启动时会触发ImportBeanDefinitionRegistrar接口的方法,将其中要注册的类注册成bean。
3、实现该接口的类拥有注册bean的能力。
//接口所有抽象方法,合并看就一个注册BeanDefinition的方法
public interface ImportBeanDefinitionRegistrar {//把自定义的类封装成BeanDefinition对象,注册到Spring里面去default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {registerBeanDefinitions(importingClassMetadata, registry);}//我们平时重写这个就可以了default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {}
}
三、接口运用场景
四、使用案例
1、案例1
自定义业务类UserServiceTest,通过ImportBeanDefinitionRegistrar将注册Spring容器中。在通过spring容器获取Bean=UserServiceTest
//业务类
public class UserServiceTest {/*** 获取用户名称* @return 用户名称*/public String getUserName(){return "测试";}
}
ImportBeanDefinitionRegistrar实现类
//注意这里不能加注解,要通过Import导入进去。
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {//业务类转成bd,注册到spring容器中注入@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//1、通过Bd工具类生成bd对象,只是这个Db对象比较纯洁没有绑定任何类BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionBuilder.getBeanDefinition();//2、设置bd绑定的类型beanDefinition.setBeanClass(UserServiceTest.class);//3、注册到spring容器中registry.registerBeanDefinition("userServiceTest",beanDefinition);}
}@Configuration
@Import(MyImportBeanDefinitionRegistrar.class)
public class AppConfigClassTest {//在配置类导入ImportBeanDefinitionRegistrar实现类
}
//测试
public static void main(String[] args) {AnnotationConfigApplicationContext AnnotationConfigApplicationContext =new AnnotationConfigApplicationContext(AppConfigClassTest.class);UserServiceTest userServiceTest = AnnotationConfigApplicationContext.getBean("userServiceTest", UserServiceTest.class);String userName = userServiceTest.getUserName();System.out.println(userName);
}
如果只是把业务类注册到Spring容器中我们通过其他注解就可以了,那么ImportBeanDefinitionRegistrar有没有更高级的玩法。
2、案例2
public interface UserServiceTestInterface {public void list();
}
//因为是接口,但是spring的容器里面是不允许注入接口的,只能是接口的实现类。如果我们写个去实现接口,那就没有什么意义了,没必要搞得那么复杂,这次我们通过代理类来完成对接口的实现。public class MyInvocationHandler implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代理类逻辑代码");return null;}
}
//注意这里不能加注解,要通过Import导入进去。
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//通过工具类生成一个bd,只是这个Db对象比较纯洁没有绑定任何类BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionBuilder.getBeanDefinition();//设置Bean的类型MyInvocationHandler,类型是实现类的类型,不是接口类型。因为在实例化的时候,调用的是设置类型所以对应的构造方法。beanDefinition.setBeanClass(MyInvocationHandler.class);//注册到Spring容器中进去registry.registerBeanDefinition("userServiceTest",beanDefinition);}
}//通过配置类,导入ImportBeanDefinitionRegistrar的实现类
@Configuration
@Import(MyImportBeanDefinitionRegistrar.class)
public class AppConfigClassTest {
}
测试
public static void main(String[] args) {AnnotationConfigApplicationContext AnnotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfigClassTest.class);//通过name获取Bean,注意此时的bean类型不是UserServiceTestInterface类型,而是MyInvocationHandlerObject userServiceTestInterface = AnnotationConfigApplicationContext.getBean("userServiceTest");if(userServiceTestInterface instanceof MyInvocationHandler){//代码实际会走到这里,把object转成带代理类。MyInvocationHandler u = (MyInvocationHandler) userServiceTestInterface;//生成接口UserServiceTestInterface的代理对象UserServiceTestInterface o = (UserServiceTestInterface) Proxy.newProxyInstance(MainTest.class.getClassLoader(), new Class[]{UserServiceTestInterface.class}, u);}
}
3、案例3
定义一个业务接口,通过FactoryBean+InvocationHandler来生成该接口的代理类,无需手动写业务接口的实现类,很多底层框架就是这样实现的。
InvocationHandler:主要是通过Invoke方法来拦截业务接口的方法
FactoryBean:主要是用来将生成的代理类。
ImportBeanDefinitionRegistrar:在这里的作用就是帮忙我们把自定义的FactoryBean注册到Spring中
//业务接口
public interface UserServiceTestInterface {public void list();
}
自定义FactoryBean这样我们控制Bean的创建的过程,实现InvocationHandler用来拦截业务接口的方法。
//创建代理类,代理UserServiceTestInterface接口,UserServiceTestInterface接口方法在执行前后都会被invoke方法拦截
//FactoryBean可以生成某一个类型Bean实例,它最大的一个作用是:可以让我们自定义Bean的创建过程
public class MyFactoryBean implements FactoryBean, InvocationHandler {//为了使这个类更好地扩展。创建更多的接口,我们定义一个参数,让他们通过参数传递进来。private Class classs;//添加一个有参的构造方法。public MyFactoryBean(Class classs){this.classs = classs;}//拦截Class的所有方法@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("diaoyonlejiekou123");return null;}//返回bean的对象。spring会自动把它add到容器里面去。@Overridepublic Object getObject() throws Exception {Class[] clazzs = new Class[]{classs};//目标类集合。//通过proxy来得到代理对象。本来最有一个参数需要穿代理类对象,但因为本类实现了InvocationHandler,所以只需传thisObject proxy = Proxy.newProxyInstance(this.getClass().getClassLoader(), clazzs, this);return proxy;//返回的这个对象,会把加到spring的容器中。}//返回要添加到容器里bean的类型@Overridepublic Class<?> getObjectType() {return this.classs;}
}
自定义ImportBeanDefinitionRegistrar实现类,把我们自定义的FactoryBean注册到Spring中。
//注意这里不能加注解,要通过Import导入进去。
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//通过工具类生成一个bd,只是这个Db对象比较纯洁没有绑定任何类BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();//为什么要转成GenericBeanDefinition这种类型。因为GenericBeanDefinition有更多修改bd属性的方法。后面我会介绍为什么要修改属性。GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionBuilder.getBeanDefinition();//这里很重要。getConstructorArgumentValues是为了获取该bd的所有构造方法,因为我们重写了有参构造方法,所有我们需要带参数过去 //不然spring没法帮我们实例化,addGenericArgumentValue是添加参数,该代码会执行两步//第一步是匹配对应的构造方法,第二步是实例化。beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(UserServiceTestInterface.class.getName());//因为代理对象类型的,实例化的时候走的是代理类的构造方法beanDefinition.setBeanClass(MyFactoryBean.class);//注册bdregistry.registerBeanDefinition("userServiceTest",beanDefinition);}
}
测试
public static void main(String[] args) {AnnotationConfigApplicationContext AnnotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfigClassTest.class);//通过name获取BeanObject userServiceTestInterface = AnnotationConfigApplicationContext.getBean("userServiceTest");//针对这种场景Bean的类型是,通过FactoryBean的getObjectType方法返回的。UserServiceTestInterface u = (UserServiceTestInterface) userServiceTestInterface;u.list();
}
相关文章:
Spring学习之ImportBeanDefinitionRegistrar接口
一、本文内容分类 1、接口功能 2、接口运用场景 3、使用案例 4、注意事项 二、接口功能介绍 描述:ImportBeanDefinitionRegistrar接口是也是spring的扩展点之一,它可以支持我们自己写的代码封装成BeanDefinition对象,注册到Spring容器中,功能类似于注…...
React 全栈体系(八)
第四章 React ajax 三、案例 – github 用户搜索 2. 代码实现 2.3 axios 发送请求 Search /* src/components/Search/index.jsx */ import React, { Component } from "react"; import axios from axiosexport default class Search extends Component {search …...
4.开放-封闭原则
这个原则其实是有两个特征,一个是说‘对于扩展是开放的(Open for extension),另一个是说‘对于更改是封闭的(Closed for modification)[ASD]。...
oracle递归with子句
比如现在想获取开始日期到结束日期每个月的月底日期,这个时候可以通过递归实现: --通过递归with子句获取开始日期到结束日期每个月的月末日期 WITH date_range (month_start, month_end) AS (SELECT TRUNC(to_date(bdate,yyyy-mm-dd), MM),LAST_DAY(to_…...
如何在Proteus进行STM32F103C8T6模拟以及keil5开发
一、下载Proteus 8和keil5 最新版 Proteus 8.15 Professional 图文安装教程(附安装包)_proteus密钥_main工作室的博客-CSDN博客Keil uVision5 5.38官方下载、安装及注册教程_keil uvision5下载_这是乐某的博客-CSDN博客 二、新建STM32F103C8项目 接下来…...
C# OpenCvSharp 图片模糊检测(拉普拉斯算子)
效果 项目 代码 using OpenCvSharp; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Windows.Forms.VisualStyl…...
志高团队:广阔前景 全新的投资理财体验
当今时代,数字金融迅猛发展,投资理财领域正在经历前所未有的重大变革。作为加拿大华企联合会控股旗下的重要项目,恒贵即将启动,旨在为广大投资者带来全新的投资理财体验。这一创新项目的优势和广阔前景受到了业内观察机构的广泛关注和期待。 恒贵作为一家全新的P2C多元化投资理…...
基于自编译的onlyoffice镜像,关于修改字体的问题
基于自编译的onlyoffice镜像,关于修改字体的问题 自编译onlyoffice镜像来自于 https://blog.csdn.net/Gemini1995/article/details/132427908 该镜像里面没有documentserver-generate-allfonts.sh文件,所以需要自己创建一个(建议放在/usr/b…...
1.wifi开发,wifi连接初次连接电脑没有识别,搭建环境
wifi连接初次连接电脑没有识别 1.不识别可能是线的问题,即使wifi的灯亮了,虽然串口却没有找到。所以解决方法就是重新来一个usb的线 一。初步使用 (1)使用ESP烧写工具(选择esp8266) (2…...
【JAVA-Day25】解密进制转换:十进制向R进制和R进制向十进制的过程
解密进制转换:十进制向R进制和R进制向十进制的过程 一、什么是进制转换1.1 进制1.2 进制转换 二、十进制转R进制2.1 转换算法2.2 示例代码 三、R进制转十进制3.1 转换算法3.2 示例代码 四、总结参考资料 ) 博主 默语带您 Go to New World. ✍ 个人主页—— 默语 的…...
牛客网字节面试算法刷题记录
NC78 反转链表 public ListNode ReverseList (ListNode head) {if(headnull) return head;ListNode phead.next,q,tailhead;tail.next null;while(p!null){q p.next;p.next tail;tail p;p q;}return tail;} NC140 排序 冒泡排序 public int[] MySort (int[] arr) {for…...
QT连接Sqlite
使用QTCreator; 根据资料,Qt自带SQLite数据库,不需要再单独安装,默认情况下,使用SQLite版本3,驱动程序为***QSQLITE***; 首先创建项目;在 Build system 中应选中qmake,…...
ChatGPT AIGC 完成各省份销售动态可视化分析
像这样的动态可视化由人工智能ChatGPT AIGC结合前端可视化技术就可以实现。 Prompt:请使用HTML,JS,Echarts 做一个可视化分析的案例,地图可视化,数据可以随机生成,请写出完整的代码 完整代码复制如下: <!DOCTYPE html> <html> <head><meta char…...
基于SpringBoot+Vue的餐饮管理系统设计与实现
前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 👇🏻…...
2023 亲测好用版VScode配置文件
tasks.json {"tasks": [{"type": "cppbuild","label": "g++",// 调试会话开始前执行的任务,一般为编译程序,c++为g++, c为gcc 和launch中preLaunchTask保持一致// "command": "D:/Users/Downloads/ming…...
jmeter基础压力教程
Jmeter基础压力测试教程 一、安装Jmeter; 安装需求:1. JDK 8.0.91安装包(最新即可,配置环境变量) 2. Badboy2.25脚本录制工具(注:Jmeter3.0与badboy2.0不兼容) Jmerter安装包…...
图片格式大全
青春不能回头,青春也没有终点。 大全介绍 图片格式有多种,每种格式都有其独特的特性和用途。以下是一些常见的图片格式以及它们的介绍: JPEG(Joint Photographic Experts Group): 文件扩展名:…...
5.14.1.2 Get Log Page – Smart Log
SMART / Health Information (Log Identifier 02h) smart log 可通过nvme cli获取如下: 同样也可以通过get-log 命令获取到原始数据如下: 此日志页用于提供SMART和常用的helath 信息。所提供的信息在控制器的使用寿命内,并在整个power cycle前后都保留。要访问控制器日志…...
【深度学习实验】线性模型(一):使用NumPy实现简单线性模型:搭建、构造损失函数、计算损失值
#【中秋征文】程序人生,中秋共享# 目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入库 1. 定义线性模型linear_model 2. 定义损失函数loss_function 3. 定义数据 4. 调用函数 一、实验介绍 使用Numpy实现 线性模型搭…...
springcloud3 分布式事务-seata的四种模式总结以及异地容灾
一 seata四种模式比较 1.1 seata的4种模式比较 二 seata的高可用 2.1架构 1.建TC服务集群非常简单,启动多个TC服务,注册到nacos即可。 2.做异地多机房容灾,比如一个TC集群在上海,另一个TC集群在杭州, 3.微服务基…...
高考解析几何“秒杀”技巧:用极点极线快速搞定椭圆定点定值难题
高考解析几何“秒杀”技巧:用极点极线快速搞定椭圆定点定值难题 解析几何作为高考数学的压轴题型,常常让考生望而生畏。面对复杂的计算和抽象的条件,如何在有限时间内快速找到突破口?极点极线理论作为高等几何中的重要工具&#x…...
Touchpoint:命令行工具集中管理工作上下文,提升开发效率
1. 项目概述:一个被低估的开发者效率工具如果你和我一样,日常开发工作需要在多个代码仓库、项目管理工具(如Jira、Linear)、文档平台(如Confluence、Notion)和沟通软件(如Slack)之间…...
告别串口线!用STM32CubeMX配置USB-CDC虚拟串口,实现与电脑免驱动通信(附Win7驱动安装指南)
STM32虚拟串口革命:USB-CDC免驱动通信全实战指南 嵌入式开发调试过程中,最令人头疼的莫过于频繁插拔串口线导致的接口松动、接触不良问题。传统串口调试不仅占用宝贵的UART资源,还常常因为物理连接问题浪费大量调试时间。本文将彻底改变这一局…...
MySQL 视图使用场景与限制
视图是把查询封装成「虚拟表」的方式,用对了简化查询,用错了性能爆炸。这篇说说视图的用法和注意事项。 什么是视图? -- 视图:保存好的 SQL 查询,像表一样使用 CREATE VIEW view_name AS SELECT column1, column2 FROM…...
自主智能体框架构建指南:从LLM工具调用到多任务规划系统
1. 项目概述:一个能“开疆拓土”的智能体框架最近在开源社区里,一个名为njbrake/agent-of-empires的项目引起了我的注意。光看这个名字,就充满了野心和想象力——“帝国的代理人”。这可不是一个简单的脚本工具,而是一个旨在构建能…...
EmoLLM:大语言模型的情感增强训练与部署实践
1. 项目概述:当大语言模型学会“察言观色”最近在折腾一个挺有意思的开源项目,叫SmartFlowAI/EmoLLM。光看名字你大概能猜到,这玩意儿跟“情绪”和“大语言模型”有关。没错,它的核心目标就是让冷冰冰的LLM(Large Lang…...
龙芯3A6000平台Loongnix系统部署实战:从固件更新到驱动配置全解析
1. 项目概述:一次国产平台上的系统部署实战最近,我拿到了一台基于龙芯3A6000处理器和7A2000桥片的国产台式机。对于长期在x86/ARM生态里打转的开发者来说,这无疑是一个充满新鲜感和挑战的“新玩具”。它的核心使命,就是运行龙芯社…...
解密ComfyUI-WanVideoWrapper:在ComfyUI中突破AI视频生成的技术壁垒
解密ComfyUI-WanVideoWrapper:在ComfyUI中突破AI视频生成的技术壁垒 【免费下载链接】ComfyUI-WanVideoWrapper 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-WanVideoWrapper 你是否曾想过将脑海中的创意场景转化为生动的视频内容࿰…...
Maestro:基于YAML的声明式任务编排引擎,实现DevOps自动化工作流
1. 项目概述:从“指挥家”到“自动化交响乐”在软件开发和运维的世界里,我们常常扮演着“救火队员”的角色。一个微服务挂了,需要手动登录服务器查看日志;一个API接口响应慢了,得去翻监控图表找原因;新功能…...
量子优化算法在组合优化问题中的应用与性能分析
1. 量子优化算法与组合优化问题概述组合优化问题广泛存在于物流调度、网络设计、芯片布局等工业场景中,其核心挑战在于从离散解空间中高效寻找最优解。传统经典算法在面对NP难问题时往往面临计算复杂度爆炸的困境。量子优化算法通过量子叠加和纠缠等特性,…...
