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…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
