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.微服务基…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
