Spring揭秘:BeanDefinitionRegistry应用场景及实现原理!

Spring揭秘:BeanDefinitionRegistry应用场景及实现原理! - 程序员古德

内容概要

BeanDefinitionRegistry接口提供了灵活且强大的Bean定义管理能力,通过该接口,开发者可以动态地注册、检索和移除Bean定义,使得Spring容器在应对复杂应用场景时更加游刃有余,增强了Spring容器的可扩展性和动态性,为开发者带来了更大的灵活性和控制力。

核心概念

它能用来干啥?

BeanDefinitionRegistry接口负责注册和管理Bean的定义信息,模拟一个业务案例来说明BeanDefinitionRegistry接口的作用。

假设,有一家大型餐厅,餐厅里有各种各样的员工,包括厨师、服务员、清洁工等,每个员工都有自己的职责和技能要求,餐厅的运营离不开这些员工的协同工作。

在这里,员工就相当于Spring框架中的Bean,而员工的职责和技能要求则对应Bean的定义信息,BeanDefinitionRegistry就像是餐厅的员工信息管理系统。

当招聘新员工时,会将他们的信息(姓名、职位、技能等)录入到这个系统中,同样地,在Spring框架中,当定义一个Bean时,Spring会将这个Bean的定义信息注册到BeanDefinitionRegistry中。

使用场景

  1. 员工招聘与注册:当餐厅需要招聘新员工时,会通过招聘流程确定员工的职位和技能要求,然后将这些信息录入到员工信息管理系统中,在Spring中,这相当于定义一个新的Bean,并将其注册到BeanDefinitionRegistry中。
  2. 员工信息查询与调度:当餐厅有工作任务需要完成时,会根据任务的要求,从员工信息管理系统中查询具备相应技能的员工,并安排他们执行任务,在Spring中,这相当于根据依赖关系从BeanDefinitionRegistry中查找并创建Bean的实例。
  3. 员工信息更新与维护:随着餐厅的运营,员工的职责或技能要求可能会发生变化,会及时更新员工信息管理系统中的信息,以确保信息的准确性,在Spring中,如果Bean的定义发生变化(例如,通过修改配置文件或注解),BeanDefinitionRegistry中的信息也会相应更新。

它有哪些特性?

BeanDefinitionRegistry接口主要用于解决Spring IoC容器中Bean定义信息的注册、存储和管理相关的技术问题。

BeanDefinitionRegistry接口提供了向Spring IoC容器注册Bean定义信息的方法,允许开发者在运行时动态地向容器中添加或修改Bean的定义。

BeanDefinitionRegistry可以解决如下类似的技术问题:

  1. Bean定义的注册:在Spring中,Bean的定义通常以配置文件(如XML)或注解的形式存在,BeanDefinitionRegistry提供了注册这些定义的方法,使得Spring IoC容器能够在运行时知道如何创建和管理这些Bean的实例。
  2. Bean定义的存储BeanDefinitionRegistry内部维护了一个用于存储Bean定义的注册表,这个注册表能够高效地存储和检索Bean的定义信息,从而支持Spring IoC容器的依赖注入和自动装配功能。
  3. Bean定义的动态管理:通过BeanDefinitionRegistry,开发者可以在运行时动态地添加、修改或删除Bean的定义。
  4. 支持多种配置方式BeanDefinitionRegistry与Spring的配置机制紧密结合,支持基于XML、注解、Java配置类等多种配置方式。
  5. 促进模块化和可扩展性:通过将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();  }  
}

当运行ClientAppmain方法时,会在控制台上看到输出:“Doing something in SimpleService”

核心API

BeanDefinitionRegistry接口是Spring IoC容器的一部分,它负责管理和维护Bean定义(BeanDefinition)。

BeanDefinition是Spring用来描述系统中Bean的元数据,包括Bean的类名、作用域、初始化方法、属性等信息。BeanDefinitionRegistry接口提供了一系列方法来注册、检索和删除这些Bean定义。

以下是BeanDefinitionRegistry接口中主要方法的含义:

  1. void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;

    这个方法用于注册一个Bean定义。它接受一个Bean名称(beanName)和一个对应的Bean定义(beanDefinition)。如果注册过程中发生错误,比如Bean名称已经存在,它会抛出BeanDefinitionStoreException异常。

  2. void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    这个方法用于从注册表中移除一个已经注册的Bean定义。它接受一个Bean名称作为参数。如果Bean定义不存在,它会抛出NoSuchBeanDefinitionException异常。

  3. BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    这个方法用于根据Bean名称检索一个Bean定义。如果找不到对应的Bean定义,它会抛出NoSuchBeanDefinitionException异常。

  4. boolean containsBeanDefinition(String beanName);

    这个方法用于检查注册表中是否包含指定名称的Bean定义。如果包含,返回true;否则返回false

  5. String[] getBeanDefinitionNames();

    这个方法返回注册表中所有Bean定义的名称数组。

  6. int getBeanDefinitionCount();

    这个方法返回注册表中Bean定义的数量。

  7. boolean isBeanNameInUse(String beanName);

    这个方法检查给定的Bean名称是否已经被使用。如果已经被使用,返回true;否则返回false。这个方法通常用于在注册新的Bean定义之前检查名称是否冲突。

技术原理

BeanDefinitionRegistry是Spring框架中用于注册、保存和管理BeanDefinition的接口,BeanDefinition是Spring用来描述系统中Bean的配置信息的接口,包括Bean的类名、作用域、属性、依赖等信息。

BeanDefinitionRegistry接口的实现类通常会将BeanDefinition存储在一个Map结构的数据集中,以便于根据Bean的名称快速查找对应的BeanDefinition

在Spring框架中,DefaultListableBeanFactoryBeanDefinitionRegistry接口的一个典型实现。

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的其他部分(比如BeanFactoryApplicationContext)来完成的,当需要实例化一个Bean时,Spring会根据BeanDefinition中的信息来创建Bean的实例,并进行依赖注入。

核心总结

Spring揭秘:BeanDefinitionRegistry应用场景及实现原理! - 程序员古德

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全面解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/729275.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++那些事儿】函数重载与C++中的“指针“——引用

君兮_的个人主页 即使走的再远,也勿忘启程时的初心 C/C 游戏开发 Hello,米娜桑们,这里是君兮_,我之前看过一套书叫做《明朝那些事儿》,把本来枯燥的历史讲的生动有趣。而C作为一门接近底层的语言,无疑是抽象且难度颇…

为什么RTX 4090更受欢迎

RTX 4090作为顶级显卡,凭借高性能和高图形处理能力,特别适合游戏、专业图形设计和人工智能领域,备受专业游戏玩家和高性能计算需求开发者的青睐。 RTX 4090高速复杂的计算能力 RTX 4090 GPU拥有 760 亿个晶体管、16384 个 CUDA 核心和 24 GB…

nestjs10.x使用jwt生成token

1 安装依赖: pnpm install --save nestjs/jwtpnpm install passport passport-jwt nestjs/jwtpnpm install types/passport-jwt --save-dev 2 可以使用命令新建auth鉴权文件夹 nest g mo auth // auth.module.ts nest g s auth // auth.service.ts nest g co …

杠杆和保证金有什么关系?WeTrade众汇一个公式讲清楚

在交易中杠杆其实就是一种期权,它能增加交易者作为抵押品的资金,以建立和维持头寸。 例如,1:100的操作杠杆,在这种情况下,意味着开立1000单位基础货币的头寸,交易者将需要少100倍的资金,即10个…

C++常量和变量

甲流疫情死亡率 甲流并不可怕,在中国,它的死亡率并不是很高。根据截至2009年12月22日各省报告的甲流确诊数和死亡数,计算甲流在各省的死亡率 输入 一行,有两个整数,第1个为确诊数,第2个为死亡数 输出 一…

学习Java的第四天

目录 一、if选择结构 1、基本if选择结构 语法结构: 流程图: 示例: 2、if-else 选择结构 语法结构: 流程图: 示例: 3、多重if选择结构 语法结构: 流程图: 示例&#xff1a…

【Docker】若依ruoyi项目部署

一 搭建局域网 1 # 搭建net-ry局域网,用于部署若依项目docker network create net-ry --subnet172.68.0.0/16 --gateway172.68.0.1 # 注意1:关闭宿主机的防火墙,否者容器内部的MySQL、redis等服务,外部访问不了;开放…

【REST2SQL】12 REST2SQL增加Token生成和验证

【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 【REST2SQL】04 REST2SQL第一版Oracle版实现 【REST2SQL】05 GO 操作 达梦 数据库 【REST2SQL】06 GO 跨包接口重构代码 【REST2SQL】07 GO 操作 Mysql 数据库 【RE…

Docker_搭建跨服务器网络通讯(swarm 集群)

本文目录 一、如何搭建docker的跨服务器网络1、在主服务器上初始化docker swarm 集群2、其他服务器节点加入到创建好的集群中3、检验集群是否搭建成功4、创建overlay类型的docker网络 二、如何部署服务1、docker部署2、docker-compose部署 一、如何搭建docker的跨服务器网络 1…

《小学科学》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答: 问:《小学科学》期刊是正规期刊吗? 答:是正规期刊,下面会有具体介绍 问:《小学科学》期刊是什么级别的? 答:省级;主管单位:长春出版传媒集团有…

unicloud 创建云函数并使用云函数

云函数是什么 云函数即在云端(服务器端)运行的函数。 从 HBuilderX 3.4起,新增了云函数的扩展版,云对象。 开发者无需购买、搭建服务器,只需编写代码并部署到云端即可在客户端(App/Web/小程序等&#xf…

【Linux】第一个小程序--进度条

这篇博客要综合利用以前的知识,来实现一个进度条程序~ 目录 换行&回车 缓冲区 实现简单的倒计时 实现进度条 version1 version2 在开始写这个小程序之前,我们先学习一些预备知识: 换行&回车 缓冲区 在我们运行这个程序时&…

如何阅读“计算机界三大神书”之一 ——《计算机程序的构造和解释》SICP

👨‍🎓博主简介 🏅云计算领域优质创作者   🏅华为云开发者社区专家博主   🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 🐋 希望大家多多支…

STM32CubeMX学习笔记17--- FSMC

1.1 TFTLCD简介 TFT-LCD(thin film transistor-liquid crystal display)即薄膜晶体管液晶显示器。液晶显示屏的每一个像素上都设置有一个薄膜晶体管(TFT),每个像素都可以通过点脉冲直接控制,因而每个节点都…

论文阅读:Scalable Diffusion Models with Transformers

Scalable Diffusion Models with Transformers 论文链接 介绍 传统的扩散模型基于一个U-Net骨架,这篇文章提出了一种新的扩散模型结构,将U-Net替换为一个transformer,并将这种结构称为Diffusion Transformers (DiTs)。他们还发现&#xff…

python77-Python的函数参数,个数可变参数

很多编程语言都允许定义个数可变的参数,这样可以在调用函数时传入任意多个参数。Python当然也不例外,Python 允许在形参前面添加一个星号(*),这样就意味着该参数可接收多个参数值,多个参数值被当成元组传入。下面程序定义了一个形参个数可变的函数。 # !/usr/bin/env pyth…

阿里云服务器使用教程_2024建站教程_10分钟网站搭建流程

使用阿里云服务器快速搭建网站教程,先为云服务器安装宝塔面板,然后在宝塔面板上新建站点,阿里云服务器网aliyunfuwuqi.com以搭建WordPress网站博客为例,来详细说下从阿里云服务器CPU内存配置选择、Web环境、域名解析到网站上线全流…

Vscode连接远程服务器失败解决方案

一、 could not establish connection to “XXX” 尝试使用Remote-SSH插件连接远程的服务器,但是配置显示出错,端口显示试图写入的管道不存在,弹出窗口显示could not establish connection to “XXX” 二、检查Windows的OpenSSH 1.检索是否…

Java中注解@RequestParam 和 @ApiParam详解

一、RequestParam 和 ApiParam的常用属性 RequestParam 和 ApiParam 是在 Spring MVC 控制器方法中使用的注解,它们分别服务于不同的目的: RequestParam RequestParam 是 Spring MVC 中用来处理 HTTP 请求参数的注解,主要用于绑定请求中的查…

数据分析项目[开发中]

学习进度记录: 12.7: 教程链接:智能 BI 项目教程(一) (yuque.com) 前端: Ant Design Pro:开始使用 - Ant Design Pro​​​​​​ 然后安装依赖 yarn install 去除不需要的: 移除国际化 【报错】 …