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.hqwc.cn/news/519660.html

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

相关文章

试用Claude3

1 简介 好消息是,2024 年 3 月 4 日发布了 Claude3,据传比 GPT-4 更好,snooet 版本可以免费试用,坏消息是我们这儿不能用。 在官网注册时,需要选择国家并使用手机接收短信验证码。而在选项中没有中国这个选项。即使成…

蓝桥杯(3.7)

P1102 A-B 数对 import java.util.Scanner; public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int c sc.nextInt();int[] res new int[n1];for(int i1;i<n;i)res[i] sc.nextInt();int sum 0;for(i…

吴恩达深度学习笔记:神经网络的编程基础2.1-2.3

目录 第一门课&#xff1a;神经网络和深度学习 (Neural Networks and Deep Learning)第二周&#xff1a;神经网络的编程基础 (Basics of Neural Network programming)2.1 二分类(Binary Classification)2.2 逻辑回归(Logistic Regression) 第一门课&#xff1a;神经网络和深度学…

相机标定实验

相机标定 文章目录 相机标定1 ROS标定1.1安装标定程序1.2 下载标定板1.3 标定1.4 标定结果 2 Kalibr相机标定2.1 下载官方提供的标定板2.2 自定义标定板2.3 cam数据录制2.4 标定2.5 输出结果 3 MATLAB标定3.1 打开工具3.2 添加标定板图片3.3 设置标定参数3.4 生成标定结果3.5 标…

【Linux篇】gdb的使用

&#x1f49b;不要有太大压力&#x1f9e1; &#x1f49b;生活不是选择而是热爱&#x1f9e1; &#x1f49a;文章目录&#x1f49a; 1. 背景知识2. 使用 1. 背景知识 1. 程序发布的方式有两种&#xff0c;debug模式和release模式 2. Linux下&#xff0c;gcc和g编译生成的可执行…

springboot实现多线程开发(使用@Async注解,简单易上手)

根据springboot的核心思想便捷开发&#xff0c;使用多线程也变得简单起来&#xff0c;通过一下几个步骤即可实现。 核心注解 EnableAsync将此注解加在启动类上&#xff0c;使项目支持多线程。 Async 使用我们的Async注解在所需要进行多线程的类上即可实现。 配置线程池 …

腾讯云服务器和阿里云服务器价格测评_2024年费用大PK

2024年阿里云服务器和腾讯云服务器价格战已经打响&#xff0c;阿里云服务器优惠61元一年起&#xff0c;腾讯云服务器61元一年&#xff0c;2核2G3M、2核4G、4核8G、4核16G、8核16G、16核32G、16核64G等配置价格对比&#xff0c;阿腾云atengyun.com整理阿里云和腾讯云服务器详细配…

WebStorm安装教程 【2023年新版安装图解】

​Webstorm相关介绍 WebStorm是一款功能强大、易用且高效的开发工具&#xff0c;为Web开发者提供了全方位的支持。无论是初学者还是经验丰富的开发者&#xff0c;都能从中受益。如果你想要提高开发效率、减少出错概率&#xff0c;不妨试试WebStorm&#xff0c;它将成为你的得力…

WEB自动化测试----------Webdriver API 的使用

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

动态规划(算法竞赛、蓝桥杯)--乱杀的状态压缩DP

1、B站视频链接&#xff1a;E25 状态压缩DP 小国王_哔哩哔哩_bilibili 题目链接&#xff1a;[SCOI2005] 互不侵犯 - 洛谷 #include <bits/stdc.h> using namespace std; int n,k;//棋盘行数、国王总数 int cnt;//一行合法状态的个数 int s[1<<12];//一行合法状态…

GCN 翻译 - 2

2 FAST APROXIMATE CONVOLUTIONS ON GRAPHS 在这一章节&#xff0c;我们为这种特殊的的图基础的神经网络模型f(X, A)提供理论上的支持。我们考虑一个多层的图卷积网络&#xff08;GCN&#xff09;&#xff0c;它通过以下方式进行层间的传播&#xff1a; 这里&#xff0c;是无…

调用Mybatis plus中的saveBatch方法报找不到表的问题

1.问题现象 在用Mybatis plus开发的项目中&#xff0c;用自带的API批量保存的方法saveBatch操作时&#xff0c;发现报没有找到表的错误。 错误日志截图如下&#xff1a; 表实际是存在的&#xff0c;且发现其他的方法都没有问题&#xff0c;包括save、update等单个的方法&…