Spring系列 BeanDefinitionRegistry解读(超通俗易懂)

一、什么是BeanDefinitionRegistry?

想要弄清楚什么是BeanDefinitionRegistry,首先得知道什么是BeanDefinition。不清楚的小伙伴可以先看此篇文章:什么是BeanDefinition

简单说明一下:在Spring中,一个Bean就是被Spring管理的对象,而一个BeanDefinition则是一个Bean的配置描述,它描述了Bean的元数据,包括类名、是否为抽象类、构造函数和属性值等相关信息,这些元数据是告诉Spring如何创建和初始化相对应的Bean。

那么什么是BeanDefinitionRegistry呢?
可以这么理解:一个存放BeanDefinition的注册表,用于存储和管理所有的BeanDefinition。

BeanDefinitionRegistry源码如下:

public interface BeanDefinitionRegistry extends AliasRegistry {
 
   // 注册一个 BeanDefinition
   void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
 
   // 根据 beanName 删除一个 BeanDefinition
   void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
 
   // 根据 beanName 获得一个 BeanDefinition
   BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
 
   // 根据 beanName 判断是否包含一个 BeanDefinition
   boolean containsBeanDefinition(String beanName);
 
 
   // 返回所有存在 BeanDefinition 的名字
   String[] getBeanDefinitionNames();
 
 
   // 返回 BeanDefinition 的个数
   int getBeanDefinitionCount();
 
 
   // 根据 beanName 判断该 Bean 是否被注册
   boolean isBeanNameInUse(StringbeanName);
 
}

二、BeanDefinition有什么作用?

资源解析的统一性

BeanDefinition作为一个统一的数据结构存储了Bean相关配置信息,但是Spring有不同的配置方式,包括XML、注解以及Java配置。如果不使用BeanDefinitionRegistry,我们需要各自专门的数据结构去存储和管理,会导致资源解析复杂度增加,甚至可能存在不同解析机制之间产生不一致性。

依赖查找和注入

BeanDefinitionRegistry担任了BeanDefiniiton中央注册器的角色,可以通过它快速查找BeanDefinition,不需要遍历所有不同的配置源(XML 注解 Java配置)来查找对应的BeanDefinition。

BeanDefinition不一致简单案例:

<!-- in config1.xml -->
<bean id="sampleBean" class="com.example.SampleBean1" />

<!-- in config2.xml -->
<bean id="sampleBean" class="com.example.SampleBean2" />

这里,sampleBean 在两个配置文件中都有定义,但它们引用了不同的类。如果没有BeanDefinitionRegistry集中处理这些定义,那么Spring在尝试初始化sampleBean时可能会遭遇混淆,比如Spring尝试创建ServiceA的实例并为它注入sampleBean时,就会出现一个问题:Spring应该选择哪一个sampleBean的定义?com.example.SampleBean1还是com.example.SampleBean2?

通过使用BeanDefinitionRegistry,Spring可以在应用程序启动时检测这类问题,并在Bean定义冲突或不一致时提供明确的错误消息,而不是在运行时遭遇不确定的行为或错误。

延迟初始化和作用域管理

当需要根据作用域创建Bean或进行延迟加载时,Spring容器可以直接从注册表中获取相应的BeanDefinition对象,而无需重新解析配置资源。如果没有BeanDefinitionRegistry进行统一管理的话,Spring则需要重新去解析原始的配置资源。

配置验证

当所有BeanDefinition注册到BeanDefinitionRegistry后,Spring可以进行配置校验,例如检查循环依赖、确保Bean定义的完整性等。如果没有BeanDefinitionRegistry,Spring需要在每次Bean初始化时进行检查,这不仅导致性能下降,还可能漏掉某些隐晦的配置问题。

生命周期管理

没有BeanDefinitionRegistry存储生命周期回调、初始化方法等信息,Spring在管理Bean的生命周期时,需要从原始的配置源获取这些信息。这不仅增加了管理的复杂度,还会使生命周期回调会变得复杂和笨重。

总结:使用BeanDefinitionRegistry的目的就是为了集中式、统一化去管理BeanDefinition。Spring容器可以在启动时一次性解析配置资源(XML 注解 Java配置),可以通过BeanDefinitionRegistry快速获取到所需的、特定的(延迟加载的Bean或者不同作用域的Bean)BeanDefinition对象,而无需重新解析配置资源,从而提高性能保证BeanDefinition的正确配置和行为

三、BeanDefinitionRegistry使用简单案例

我们将创建一个简单的 Bean,注册到 DefaultListableBeanFactory(它实现了 BeanDefinitionRegistry 接口),然后从工厂中获取并使用这个Bean。

package com.example.demo.bean;

public class MyBean {
    private String message;

    public void doSomething() {
        System.out.println("Hello, world!");
    }

    public void setMessage(String message){
        this.message  = message;
    }

    public void getMessage(){
        System.out.println("Your Message : " + message);
    }
}

package com.example.demo;

import com.example.demo.bean.MyBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;

public class DemoApplication {

    public static void main(String[] args) {
        // 创建 BeanDefinitionRegistry
        DefaultListableBeanFactory registry = new DefaultListableBeanFactory();

        // 创建一个 BeanDefinition
        BeanDefinition beanDefinition = new RootBeanDefinition(MyBean.class);

        // 注册 BeanDefinition
        registry.registerBeanDefinition("myBean", beanDefinition);

        // 从 BeanFactory 中获取 Bean
        MyBean myBean = registry.getBean("myBean", MyBean.class);

        // 使用 Bean
        myBean.doSomething();  // 输出:Hello, world!
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值