Spring揭秘:BeanDefinitionRegistry应用场景及实现原理!
内容概要
BeanDefinitionRegistry
接口提供了灵活且强大的Bean定义管理能力,通过该接口,开发者可以动态地注册、检索和移除Bean定义,使得Spring容器在应对复杂应用场景时更加游刃有余,增强了Spring容器的可扩展性和动态性,为开发者带来了更大的灵活性和控制力。
核心概念
它能用来干啥?
BeanDefinitionRegistry
接口负责注册和管理Bean的定义信息,模拟一个业务案例来说明BeanDefinitionRegistry
接口的作用。
假设,有一家大型餐厅,餐厅里有各种各样的员工,包括厨师、服务员、清洁工等,每个员工都有自己的职责和技能要求,餐厅的运营离不开这些员工的协同工作。
在这里,员工就相当于Spring框架中的Bean,而员工的职责和技能要求则对应Bean的定义信息,BeanDefinitionRegistry
就像是餐厅的员工信息管理系统。
当招聘新员工时,会将他们的信息(姓名、职位、技能等)录入到这个系统中,同样地,在Spring框架中,当定义一个Bean时,Spring会将这个Bean的定义信息注册到BeanDefinitionRegistry
中。
使用场景
- 员工招聘与注册:当餐厅需要招聘新员工时,会通过招聘流程确定员工的职位和技能要求,然后将这些信息录入到员工信息管理系统中,在Spring中,这相当于定义一个新的Bean,并将其注册到
BeanDefinitionRegistry
中。 - 员工信息查询与调度:当餐厅有工作任务需要完成时,会根据任务的要求,从员工信息管理系统中查询具备相应技能的员工,并安排他们执行任务,在Spring中,这相当于根据依赖关系从
BeanDefinitionRegistry
中查找并创建Bean的实例。 - 员工信息更新与维护:随着餐厅的运营,员工的职责或技能要求可能会发生变化,会及时更新员工信息管理系统中的信息,以确保信息的准确性,在Spring中,如果Bean的定义发生变化(例如,通过修改配置文件或注解),
BeanDefinitionRegistry
中的信息也会相应更新。
它有哪些特性?
BeanDefinitionRegistry
接口主要用于解决Spring IoC容器中Bean定义信息的注册、存储和管理相关的技术问题。
BeanDefinitionRegistry
接口提供了向Spring IoC容器注册Bean定义信息的方法,允许开发者在运行时动态地向容器中添加或修改Bean的定义。
BeanDefinitionRegistry
可以解决如下类似的技术问题:
- Bean定义的注册:在Spring中,Bean的定义通常以配置文件(如XML)或注解的形式存在,
BeanDefinitionRegistry
提供了注册这些定义的方法,使得Spring IoC容器能够在运行时知道如何创建和管理这些Bean的实例。 - Bean定义的存储:
BeanDefinitionRegistry
内部维护了一个用于存储Bean定义的注册表,这个注册表能够高效地存储和检索Bean的定义信息,从而支持Spring IoC容器的依赖注入和自动装配功能。 - Bean定义的动态管理:通过
BeanDefinitionRegistry
,开发者可以在运行时动态地添加、修改或删除Bean的定义。 - 支持多种配置方式:
BeanDefinitionRegistry
与Spring的配置机制紧密结合,支持基于XML、注解、Java配置类等多种配置方式。 - 促进模块化和可扩展性:通过将Bean定义的注册和管理逻辑封装在
BeanDefinitionRegistry
中,Spring框架实现了模块化和可扩展性。开发者可以编写自己的Bean定义注册逻辑,并将其集成到Spring IoC容器中,从而扩展容器的功能。
代码案例
下面代码演示如何使用BeanDefinitionRegistry
接口,并通过Spring IoC容器获取该bean的实例,如下代码:
package com.example.demo; public class SimpleService { public void doSomething() { System.out.println("Doing something in SimpleService"); }
}
创建一个BeanDefinitionRegistryPostProcessor
来注册这个服务类的bean定义:
package com.example.demo; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition; public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { // 创建bean定义 GenericBeanDefinition beanDefinition = new GenericBeanDefinition(); // 设置bean的类 beanDefinition.setBeanClassName("com.example.demo.SimpleService"); // 注册bean定义 registry.registerBeanDefinition("simpleService", beanDefinition); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // 这里可以进行其他的BeanFactory后处理,但不是必须的 }
}
然后,配置Spring来使用的CustomBeanDefinitionRegistryPostProcessor
:
package com.example.demo; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
public class AppConfig { @Bean public CustomBeanDefinitionRegistryPostProcessor customBeanDefinitionRegistryPostProcessor() { return new CustomBeanDefinitionRegistryPostProcessor(); }
}
最后,写一个客户端调用代码来启动Spring应用并获取注册的bean实例:
package com.example.demo; import org.springframework.context.ConfigurableApplicationContext; public class ClientApp { public static void main(String[] args) { // 创建应用上下文 ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 从上下文中获取注册的bean SimpleService simpleService = context.getBean(SimpleService.class); // 调用bean的方法 simpleService.doSomething(); // 关闭应用上下文 context.close(); }
}
当运行ClientApp
的main
方法时,会在控制台上看到输出:“Doing something in SimpleService”
。
核心API
BeanDefinitionRegistry
接口是Spring IoC容器的一部分,它负责管理和维护Bean定义(BeanDefinition
)。
BeanDefinition
是Spring用来描述系统中Bean的元数据,包括Bean的类名、作用域、初始化方法、属性等信息。BeanDefinitionRegistry
接口提供了一系列方法来注册、检索和删除这些Bean定义。
以下是BeanDefinitionRegistry
接口中主要方法的含义:
-
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
这个方法用于注册一个Bean定义。它接受一个Bean名称(
beanName
)和一个对应的Bean定义(beanDefinition
)。如果注册过程中发生错误,比如Bean名称已经存在,它会抛出BeanDefinitionStoreException
异常。 -
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
这个方法用于从注册表中移除一个已经注册的Bean定义。它接受一个Bean名称作为参数。如果Bean定义不存在,它会抛出
NoSuchBeanDefinitionException
异常。 -
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
这个方法用于根据Bean名称检索一个Bean定义。如果找不到对应的Bean定义,它会抛出
NoSuchBeanDefinitionException
异常。 -
boolean containsBeanDefinition(String beanName);
这个方法用于检查注册表中是否包含指定名称的Bean定义。如果包含,返回
true
;否则返回false
。 -
String[] getBeanDefinitionNames();
这个方法返回注册表中所有Bean定义的名称数组。
-
int getBeanDefinitionCount();
这个方法返回注册表中Bean定义的数量。
-
boolean isBeanNameInUse(String beanName);
这个方法检查给定的Bean名称是否已经被使用。如果已经被使用,返回
true
;否则返回false
。这个方法通常用于在注册新的Bean定义之前检查名称是否冲突。
技术原理
BeanDefinitionRegistry
是Spring框架中用于注册、保存和管理BeanDefinition
的接口,BeanDefinition
是Spring用来描述系统中Bean的配置信息的接口,包括Bean的类名、作用域、属性、依赖等信息。
BeanDefinitionRegistry
接口的实现类通常会将BeanDefinition
存储在一个Map结构的数据集中,以便于根据Bean的名称快速查找对应的BeanDefinition
。
在Spring框架中,DefaultListableBeanFactory
是BeanDefinitionRegistry
接口的一个典型实现。
DefaultListableBeanFactory
内部使用一个ConcurrentHashMap
来存储BeanDefinition
,从而保证了线程安全。
当调用registerBeanDefinition
方法时,DefaultListableBeanFactory
会首先检查传入的Bean名称是否已经被使用,如果已经被使用,则会抛出一个异常。
然后,它会将BeanDefinition
添加到内部的ConcurrentHashMap
中,同时,DefaultListableBeanFactory
还会处理一些其他的逻辑,比如对BeanDefinition
进行合并、解析等。
当调用getBeanDefinition
方法时,DefaultListableBeanFactory
会直接从内部的ConcurrentHashMap
中根据Bean的名称查找对应的BeanDefinition
。
当调用removeBeanDefinition
方法时,DefaultListableBeanFactory
会从内部的ConcurrentHashMap
中移除对应的BeanDefinition
。
BeanDefinitionRegistry
接口的实现原理就是通过一个Map结构的数据集来存储和管理BeanDefinition
,实际过程中可能会根据需求进行一些额外的处理,比如合并、解析等,但是,基本的思路就是通过Map结构来实现快速查找和存储。
注意:BeanDefinitionRegistry
只是用于存储和管理BeanDefinition
,并不负责Bean的实例化和依赖注入,这些工作是由Spring的其他部分(比如BeanFactory
和ApplicationContext
)来完成的,当需要实例化一个Bean时,Spring会根据BeanDefinition
中的信息来创建Bean的实例,并进行依赖注入。
核心总结
BeanDefinitionRegistry
接口使得开发者能够灵活地注册、检索和管理Bean定义。
它提供了强大的Bean定义管理能力,支持动态地添加或移除Bean,使得Spring容器更加灵活和可扩展。
但是,直接操作BeanDefinitionRegistry
需要对Spring有一定的理解,对初学者可能较为晦涩,难度较高,且不当使用可能导致容器状态混乱。
建议在使用时尽量通过Spring提供的高级抽象来管理Bean,除非确实需要直接操作底层的Bean定义。
END!
END!
END!
往期回顾
精品文章
Spring揭秘:@import注解应用场景及实现原理!
Java并发基础:原子类之AtomicMarkableReference全面解析!
Java并发基础:concurrent Flow API全面解析
Java并发基础:CopyOnWriteArraySet全面解析
Java并发基础:ConcurrentSkipListMap全面解析
相关文章:

Spring揭秘:BeanDefinitionRegistry应用场景及实现原理!
内容概要 BeanDefinitionRegistry接口提供了灵活且强大的Bean定义管理能力,通过该接口,开发者可以动态地注册、检索和移除Bean定义,使得Spring容器在应对复杂应用场景时更加游刃有余,增强了Spring容器的可扩展性和动态性…...

蓝桥杯(3.5)
789. 数的范围 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int q sc.nextInt();int[] res new int[n];for(int i0;i<n;i)res[i] sc.nextInt();while(q-- ! 0) {int…...

434G数据失窃!亚信安全发布《勒索家族和勒索事件监控报告》
最新态势快速感知 最新一周全球共监测到勒索事件90起,与上周相比数量有所增加。 lockbit3.0仍然是影响最严重的勒索家族;alphv和cactus恶意家族也是两个活动频繁的恶意家族,需要注意防范。 Change Healthcare - Optum - UnitedHealth遭受了…...

7-18 彩虹瓶(Python)
彩虹瓶的制作过程(并不)是这样的:先把一大批空瓶铺放在装填场地上,然后按照一定的顺序将每种颜色的小球均匀撒到这批瓶子里。 假设彩虹瓶里要按顺序装 N 种颜色的小球(不妨将顺序就编号为 1 到 N)。现在工…...

php使用ElasticSearch
ElasticSearch简介 Elasticsearch 是一个分布式的、开源的搜索分析引擎,支持各种数据类型,包括文本、数字、地理、结构化、非结构化。 Lucene与ElasticSearch Apache Lucene是一款高性能的、可扩展的信息检索(IR)工具库…...

wpf prism左侧抽屉式菜单
1.首先引入包MaterialDesignColors和MaterialDesignThemes 2.主页面布局 左侧菜单显示在窗体外,点击左上角菜单图标通过简单的动画呈现出来 3.左侧窗体外菜单 <Grid x:Name"GridMenu" Width"150" HorizontalAlignment"Left" Ma…...

揭秘AI新纪元:近期人工智能发展的惊人突破与未来展望
近年来,人工智能(AI)领域的发展可谓是日新月异,其强大的潜力和广阔的应用前景引发了全球范围内的关注。本文将带您领略近期AI发展的风采,一探这个神奇领域的未来展望。 首先,让我们回顾一下近期AI领域的几…...

C语言基础练习——Day01
目录 选择题 编程题 打印从1到最大的n位数 计算日期到天数转换 选择题 1、执行下面程序,正确的输出是 int x5,y7; void swap(int x, int y) {int z;zx;xy;yz; } int main() { int x3,y8; swap(int x, int y);printf("%d,%d\n",x, y);return …...

用云手机进行舆情监测有什么作用?
在信息爆炸的时代,舆情监测成为企业和政府决策的重要工具。通过结合云手机技术,舆情监测系统在品牌形象维护、市场竞争、产品研发、政府管理以及市场营销等方面发挥着关键作用,为用户提供更智能、高效的舆情解决方案。 1. 品牌形象维护与危机…...

神经网络(neural network)
在这一章中我们将进入深度学习算法,学习一些神经网络相关的知识,这些是有更加强大的作用,更加广泛的用途。 神经元和大脑(neurons and the brain): 我们对于我们的编程的进步主要来自我们对于大脑的研究,根据我们对于大脑的研究…...

微信小程序用户登陆和获取用户信息功能实现
官方文档: https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html 接口说明: https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html 我们看官方这个图,梳理一下用户…...

2024年3月8日 晨会汇报
Good morning, colleagues! Before I dive into today’s work, I’d like to take a moment to share some updates over my work activities from yesterday and outline my agenda for today. Firstly, let me touch on the work activities from yesterday. Yesterday’…...

去电脑维修店修电脑需要注意什么呢?装机之家晓龙
每当电脑出现故障时,你无疑会感到非常沮丧。 如果计算机已过了保修期,您将无法享受制造商的免费保修服务。 这意味着您必须自费找到一家电脑维修店。 去电脑维修店并不容易。 大家一定要知道,电脑维修非常困难,尤其是笔记本电脑维…...

国家妇女节放假是法定的假日
在这个充满活力和希望的春天,我们迎来了一个特殊的节日——国家妇女节。这是一个属于所有女性的节日,是一个庆祝女性成就、关爱女性权益的时刻。在这个特殊的日子里,我们不禁要问:国家妇女节放假是法定假日吗?让我们一…...

Pytorch线性回归实现(Pycharm实现)
步骤都在注释里写清楚了,可以自己调整循环的次数观察输出的w与b和loss的值 import torch#学习率,用来进行w和b的更新 learning_rate 0.01 #1. 准备数据 #这里使用y3x0.8.也就是w3,b0.8.创造一个500行1列的数据 xtorch.rand([500,1]) y_true…...

2024新疆专升本考试报名教程详解
2024新疆专升本报名时间已经开始了,想要参加考试报名的同学可以提前准备好报名照...

unicloud 云数据库概念及创建一个云数据库表并添加记录(数据)
云数据库概念 uniCloud提供了一个 JSON 格式的文档型数据库。顾名思义,数据库中的每条记录都是一个 JSON 格式的文档。 它是 nosql 非关系型数据库,如果您之前熟悉 sql 关系型数据库,那么两者概念对应关系如下表: 关系型JSON 文…...

想交易盈利?Anzo Capital昂首资本发现了一本畅销书
要想在复杂多变的外汇市场中迅速加深了解并想通过交易每天都可以盈利,是通过每天阅读大量的书籍吗?是每天成为行业培训网络资源和论坛的常客吗?是通过花钱请有经验的交易者进行个人培训吗?还是进行EA交易呢? 都不是&a…...

美国站群服务器租用需要考虑哪些关键点
美国站群服务器租用通常指的是租用位于美国数据中心的服务器,这些服务器具备多个IP地址,适合用于建立和管理多个网站(即站群)。那么美国站群服务器租用需要考虑哪些关键点,RAKsmart小编为您整理发布美国站群服务器租用需要考虑哪些关键点。 在…...

如何构建Hive数据仓库Hive 、数据仓库的存储方式 以及hive数据的导入导出
什么是Hive hive是基于Hadoop的一个数据仓库工具,可以将结构化数据映射为一张表。 hive支持使用sql语法对存储的表进行查询 (本质上是把sql转成mapreduce的任务执行) Hive有三个特点: hive所存储的数据是放在HDFS文件系统中的h…...

【Linux】软件管理器yum和编辑器vim
🔥博客主页: 小羊失眠啦. 🎥系列专栏:《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞👍收藏⭐评论✍️ 文章目录 一、Linux下安装软件的方案1.1 源代码安装1.2 rpm安装1.3 yum安装 二、Linux软件…...

怎么才能确定螺栓是拧紧了——SunTorque智能扭矩系统
螺栓拧紧的标准并非仅仅依赖于螺栓的外观,而是依赖于几个关键因素,包括扭矩、预紧力和材料疲劳等。下面SunTorque智能扭矩系统和大家将详细讨论这些因素,并给出如何判断螺栓是否已经拧紧的方法。 SunTorque智能扭矩系统 首先,让我…...

西门子S120故障报警F30003的解决办法总结
西门子S120故障报警F30003的解决办法总结 如下图所示,压机在回程时突然出现报警,故障代码为:30003, 如下图所示,查找手册可以看到F30003的报警分析为:直流母线欠压 如下图所示,本来想测量输入端…...

探索vue框架的世界: 内部、外部样式和内联样式动态绑定的方法
在实际项目中,经常会遇到这样的场景,可以通过逻辑层中设定的变量,在视图层中来呈现不同的样式,那么这种动态绑定样式的方式如何实现呢? 本篇文章,博主将和大家分享动态绑定内联样式style 和 动态绑定内部和…...

代码随想录算法训练营第三十八天|动态规划|理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯
理论基础 文章 说实话,没做过题连理论基础都看不懂 1 确定dp数组(dp table)以及下标的含义 2 确定递推公式 3 dp数组如何初始化 4 确定遍历顺序 5 举例推导dp数组 这道题目我举例推导状态转移公式了么? 我打印dp数组的日志了么&…...

运维知识点-JBoss
JBoss 介绍介绍 JBoss是一个基于J2EE的开放源代码的应用服务器,也是一个运行EJB(Enterprise JavaBean)的容器和服务器。它支持EJB 1.1、EJB 2.0和EJB3的规范,体现了J2EE规范中最新的技术。JBoss遵循LGPL许可,可以在任何商业应用中免费使用,并且由开源社区开发,这使得JB…...

HarmonyOS—配置编译构建信息
在进行应用/服务的编译构建前,需要对工程和编译构建的Module进行设置。API Version 9、API Version 8与API Version 4~7的构建体系不同,因此在设置编译构建信息时也存在差异: API Version 9:需要对构建配置文件、构建脚本、应用依…...

Chrome浏览器好用的几个扩展程序
Chrome好用的扩展程序 背景目的介绍JsonHandle例子未完待续。。。。。。 背景 偶然在往上看到Chrome有很多好用的扩展程序,比较好用,因此记录下比较实用的扩展程序。 目的 记录Chrome浏览器好用的插件。 介绍 JsonHandle下载以及无法扩展插件的解决…...

Enzo Life Sciences Cortisol(皮质醇) ELISA kit
皮质醇又称为氢化可的松,是一种由胆固醇合成的类固醇激素。它是肾上腺皮质产生和分泌的主要糖皮质激素。皮质醇在血液中以游离皮质醇的形式存在,或与皮质类固醇结合球蛋白(CBG)结合。皮质醇水平在早上7点左右最高,晚上最低。皮质醇可以调节新…...

面试经典150题 -- 二分查找 (总结)
总的链接 : 面试经典 150 题 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台 二分算法模板 : 详见 : 基础二分学习笔记-CSDN博客 35 . 搜索插入位置 链接 : . - 力扣(LeetCode) 思路 : 用二分查找第一个>t…...