前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Spring揭秘:BeanDefinitionRegistry应用场景及实现原理!

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

原创
作者头像
程序员古德
发布于 2024-03-08 01:44:30
发布于 2024-03-08 01:44:30
2300
举报
文章被收录于专栏:Spring核心基础Spring核心基础
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的实例,如下代码:

代码语言:java
AI代码解释
复制
package com.example.demo;  
  
public class SimpleService {  
    public void doSomething() {  
        System.out.println("Doing something in SimpleService");  
    }  
}

创建一个BeanDefinitionRegistryPostProcessor来注册这个服务类的bean定义:

代码语言:java
AI代码解释
复制
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

代码语言:java
AI代码解释
复制
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实例:

代码语言:java
AI代码解释
复制
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异常。

  1. void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

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

  1. BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

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

  1. boolean containsBeanDefinition(String beanName);

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

  1. String[] getBeanDefinitionNames();

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

  1. int getBeanDefinitionCount();

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

  1. 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应用场景及实现原理! - 程序员古德
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全面解析

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Spring高手之路12——BeanDefinitionRegistry与BeanDefinition合并解析
BeanDefinitionRegistry 是一个非常重要的接口,存在于 Spring 的 org.springframework.beans.factory.support 包中,它是 Spring 中注册和管理 BeanDefinition 的核心组件。
砖业洋__
2023/08/18
7370
Spring高手之路12——BeanDefinitionRegistry与BeanDefinition合并解析
【小家Spring】Spring的Bean定义注册中心BeanDefinitionRegistry详解
Spring Framework最重要的一个概念就是Bean,而Spring Bean定义是需要扫描、注册来实现统一的管理的。
YourBatman
2019/09/03
1.1K0
【小家Spring】Spring的Bean定义注册中心BeanDefinitionRegistry详解
Spring 源码分析(二)之 Spring IOC 容器源码分析
spring.xml文件中保存了我们对Bean的描述配置,BeanFactory会读取这些配置然后生成对应的Bean。
zoro
2019/04/11
5351
Spring 源码分析(二)之 Spring IOC 容器源码分析
设计模式终章----手写IOC容器
核心容器,AOP和设备支持,数据访问和集成,Web组件,通信报文和集成测试,下面是Spring框架的总体架构图:
大忽悠爱学习
2021/11/15
4330
Spring-BeanFactory解读
Spring通过一个配置文件描述Bean和Bean之间的依赖关系,利用Java反射功能实例化Bean,并建立Bean之间的依赖关系。
小小工匠
2021/08/16
2070
【死磕 Spring】----- IOC 之 BeanDefinition 注册机
将定义 bean 的资源文件解析成 BeanDefinition 后需要将其注入容器中,这个过程由 BeanDefinitionRegistry 来完成。
用户1655470
2019/03/06
9010
【死磕 Spring】----- IOC 之 BeanDefinition 注册机
Spring高手之路13——BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor解析
BeanFactoryPostProcessor位于org.springframework.beans.factory.config包中。它与BeanPostProcessor有相似的核心逻辑,但它们之间的主要区别在于它们所操作的对象。BeanFactoryPostProcessor的主要目的是对Bean的配置元数据进行操作,这意味着它可以影响Bean的初始配置数据。
砖业洋__
2023/08/31
2K0
Spring高手之路13——BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor解析
Spring框架源码分析(IoC):BeanFactory和ApplicationContext容器家族
组件扫描:自动发现应用容器中需要创建的Bean。 自动装配:自动满足Bean之间的依赖。
星如月勿忘初心
2020/08/01
9440
Spring框架源码分析(IoC):BeanFactory和ApplicationContext容器家族
逐行阅读Spring5.X源码(四) BeanFactory——核心容器bean工厂
5.DefaultSingletonBeanRegistry。SingletionBean注册器的默认实现,同时继承SimpleAliasRegistry。因此这个类可以有别名注册的功能和单例bean注册的功能,并且他还支持注册DisposableBean实例;它依赖ObjectFactory接口和DisposableBean接口(关闭注册表时调用到了destroy方法)。侧重于Bean的注册,销毁,以及依赖关系(关联关系)的注册和销毁。
源码之路
2020/09/04
1.3K0
逐行阅读Spring5.X源码(四) BeanFactory——核心容器bean工厂
聊聊Spring的bean覆盖(存在同名name/id问题),介绍Spring名称生成策略接口BeanNameGenerator【享学Spring】
众所周知,Spring容器可以简单粗暴的把它理解为一个大大的Map,存储着容器所管理的所有的单实例对象。我们从使用getBean(String beanName)方法,根据bean名称就能获得容器内唯一的Bean实例就能“证明”到这一点。
YourBatman
2019/09/03
15.1K3
聊聊Spring的bean覆盖(存在同名name/id问题),介绍Spring名称生成策略接口BeanNameGenerator【享学Spring】
Spring IOC容器分析(1) -- BeanFactory
搭建好源码阅读环境后,就可以慢慢走进Spring殿堂了。IOC是Inversion of Control的缩写,控制反转的意思。很多人可能都知道IOC是spring的核心,将对象的创建初始化等权限交由
YGingko
2017/12/28
8150
Spring IOC容器分析(1) -- BeanFactory
Spring高手之路8——Spring Bean模块装配的艺术:@Import详解
在Spring中,手动装配通常是指通过XML配置文件明确指定Bean及其依赖,或者在代码中直接使用new关键字创建对象并设定依赖关系。
砖业洋__
2023/07/14
6680
Spring高手之路8——Spring Bean模块装配的艺术:@Import详解
Spring IOC容器分析(3) -- DefaultListableBeanFactory
本文介绍了Spring IOC容器中Bean的创建和依赖注入的过程,以及通过代码示例和流程图对整个过程进行了详细的解释。首先介绍了Spring IOC的基本概念和作用,然后详细阐述了Bean的创建和依赖注入的过程,最后通过代码示例和流程图演示了如何使用Spring IOC来实现Bean的创建和依赖注入。
YGingko
2017/12/28
3.3K0
Spring IOC容器分析(3) -- DefaultListableBeanFactory
Spring复杂的BeanFactory继承体系该如何理解? ----上
Spring提供了两种容器类型:BeanFactory和ApplicationContext。
大忽悠爱学习
2022/05/10
1.9K0
Spring复杂的BeanFactory继承体系该如何理解? ----上
Spring源码解析之IOC容器
在认真学习Rod.Johnson的三部曲之一:顺便也看了看源代码想知道个究竟,抛砖引玉,有兴趣的同志一起讨论研究吧!
I Teach You 我教你
2023/07/18
1940
【小家Spring】BeanFactory体系和ApplicationContext体系,两大体系各接口分析、区别和联系
前面已经讲述了很多Spring容器启动、解析、依赖注入等等源码层面的东西了,但是小伙伴有没有一种感觉就是:Spring的设计者把面向对象使用到了极致(使用得非常的好),并且它吧职责单一原则也是使用到了极致。
YourBatman
2019/09/03
1.9K0
【小家Spring】BeanFactory体系和ApplicationContext体系,两大体系各接口分析、区别和联系
Spring知识——IOC容器
1、理解: (1)控制反转。将生成对象的控制权交IOC容器,由容器生成依赖的对象。调用类只依赖接口,而不依赖具体的实现类,减少了耦合。在运行的时候,才由容器将具体的实例注入到调用类的对象中。 (2)依赖注入,就是向Ioc容器索要bean的过程。getBean是依赖注入的起点。依赖注入的过程是用户第一次向Ioc容器索要Bean时触发的。 (3)生成bean的两种方式 a、通过反射调用构造函数 b、通过CGLib 2、优点: (1)依赖关系的管理被反转并交给容器,使复杂的依赖关系管理从应用中解放出来。 (2)代码解耦 3、启动过程(依赖注入的实现过程): a、Resource寻找资源(XML文件形式的beanDefinition) b、将XML文件载入内存中,解析成org.springframework.beans.factory.config.BeanDefinition对象 c、将org.springframework.beans.factory.config.BeanDefinition对象注册到HashMap容器中 d、客户想Ioc容器索要bean,触发依赖注入
用户5325874
2020/01/16
5540
《Spring核心技术》第1章:震惊!我竟然写了三万字解析@Configuration注解
作者:冰河 星球:http://m6z.cn/6aeFbs 博客:https://binghe.gitcode.host 文章汇总:https://binghe.gitcode.host/md/all/all.html 源码地址:https://github.com/binghe001/spring-annotation-book
冰河
2023/02/21
6500
《Spring核心技术》第1章:震惊!我竟然写了三万字解析@Configuration注解
面试系列-spring-ioc原理
低级容器BeanFactory可以理解为就是个HashMap,Key是BeanName,Value是Bean实例,通常只提供注册(put),获取(get)这两个功能;是IOC容器的基础接口,所有的容器都是从它这里继承实现而来,BeanFactory作为SpringIOC容器,管理着Bean的生命周期,控制着Bean的依赖注入;
用户4283147
2022/10/27
3450
面试系列-spring-ioc原理
给你一份长长长的 Spring Boot 知识清单(上)
一、抛砖引玉:探索Spring IoC容器1.1、Spring IoC容器1.2、Spring容器扩展机制二、夯实基础:JavaConfig与常见Annotation2.1、JavaConfig2.2、@ComponentScan2.3、@Import2.4、@Conditional2.5、@ConfigurationProperties与@EnableConfigurationProperties三、削铁如泥:SpringFactoriesLoader详解
芋道源码
2018/12/29
5890
给你一份长长长的 Spring Boot 知识清单(上)
推荐阅读
相关推荐
Spring高手之路12——BeanDefinitionRegistry与BeanDefinition合并解析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文