SingletonBeanRegistry——Spring中单例Bean管理的核心接口


思考,输出,沉淀。用通俗的语言陈述技术,让自己和他人都有所收获。

作者:毅航😜


在上一篇详解Spring中IOC容器的顶层接口中,并对Spring中常见的IOC容器进行了介绍分析。简单来看,BeanFactory作为Spring容器的顶层父类接口,其主要定义了IOC容器对于Bean实例存取的一些公共方法。在此基础上Spring还扩展出了支持Bean枚举的ListableBeanFactory接口、实现容器间继承关系的HierarchicalBeanFactory接口,以及自动装配的基石的AutowireCapableBeanFactory接口。

但如果要实现IOC的特性,仅仅依靠这几个接口是远远不够的,今天我们便继续来扒一扒与单例Bean实例相关的SingletonBeanRegistry接口。

前言

众所周知,BeanFactory作为IOC容器的顶层接口,负责管理Spring容器中的所有Bean的创建、配置和管理,并定义了获取Bean、检查Bean存在性、获取Bean类型等容器的基本操作。而Spring为了更好的管理单利Bean实例,其内部将单例Bean的管理功能抽象到SingletonBeanRegistry接口中,从而使得单例Bean的管理与其他Bean管理功能解耦。

单例Bean的管理------SingletonBeanRegistry

Spring的中,SingletonBeanRegistry的主要用于管理单例Bean的注册和获取 ,同时提供将单例Bean实例注册到注册表中的方法。其内部构造如下:

java 复制代码
public interface SingletonBeanRegistry {
  
   void registerSingleton(String beanName, Object singletonObject);

   @Nullable
   Object getSingleton(String beanName);

   boolean containsSingleton(String beanName);

   String[] getSingletonNames();

}

其中registerSingleton的作用是将一个单例Bean实例注册到注册表中,通过该方式开发人员可以手动向Spring的容器中添加单例Bean实例,而无需要通过Spring的配置文件或注解来定义这些BeangetSingleton方法则是一种的根据Bean名称获取已经注册的单例Bean实例的方法。

进一步,containsSingleton方法对外提供了检查指定名称的单例Bean是否已经注册的功能,而getSingletonNames则是允许开发者获取容器中所有单例Bean的名称。

不难发现,SingletonBeanRegistry所暴露的一些方法主要完成的工作主要为单例Bean的获取和注册。看到这你可能会觉得SingletonBeanRegistryBeanFactory功能很类似,但其实两者还是存在一定差异性。

具体来看,BeanFactorySpring的核心接口之一,其主要负责管理Spring容器中的所有Bean的创建、配置和管理。 并提供了一种高级的配置机制来管理Bean以支持不同类型的Bean的管理。

SingletonBeanRegistry则是一个专门用于管理单例Bean的接口,主要提供了注册、获取和管理单例Bean的方法 。事实上,SingletonBeanRegistry并不负责创建Bean,它的作用是维护已经创建好的单例Bean实例。

总的来看,SingletonBeanRegistry专注于单例Bean的注册和管理,而BeanFactory负责整个Spring容器中所有Bean的创建、配置和管理。 这样的设计使得每个类的职责更加单一。每个接口只承担一种责任。这样划分方式使代码更简洁、更易维护,并且更容易理解和扩展。

与此同时,将单例Bean的管理功能抽象到SingletonBeanRegistry接口中,使得单例Bean的管理与其他Bean管理功能解耦。这样,如果需要在不同的上下文中管理单例Bean,可以直接使用SingletonBeanRegistry接口,而不必依赖于整个BeanFactory接口。

例如,ConfigurableBeanFactory接口继承了SingletonBeanRegistry接口与BeanFactory。这意味着ConfigurableBeanFactory的实现类既具有完整的Bean管理功能,又具备单例Bean的管理功能。 这样的设计使得Spring框架将单例Bean管理功能与其他Bean管理功能解耦,进而实现了模块间高内聚低耦合的设计。

进一步,你可能会想既然Spring内部有对于单例Bean的管理接口,对于多例Bean是如何进行管理的呢? 要想解答这一问题,我们首先要明白Spring内部对于Bean作用域的划分。

Spring中的Bean是存在单例多例之分。具体来看,所谓的单例即在整个Bean的生命周期内,该Bean实例是唯一的。反之,如果Bean每次请求时都会创建一个新的实例,且Bean实例不会在容器中进行缓存,则该Bean的作用范围即为多例

如果一个Bean的作用范围为多例, 那么该多例Bean本身并不需要在Spring容器中全局共享和缓存,因此多例Bean的生命周期管理相对简单,其大致可以分为如下三个阶段:

  1. 创建并初始化 :当每次有请求到达Spring时,如果有对该Bean的需要,则每次创建一个新的Bean实例,然后再执行依赖注入和相关初始化方法。
  2. 使用:客户端使用Bean实例。
  3. 销毁:使用完毕后,实例会被垃圾回收机制自动回收。

(注:Spring容器不负责管理多例Bean的销毁(除非显式调用销毁方法)。)

为了更深入理解多例Bean,我们通过一个简单的代码来展示对于多例Bean的定义和获取过程。

java 复制代码
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

public class PrototypeBeanExample {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        PrototypeBean bean1 = context.getBean(PrototypeBean.class);
        PrototypeBean bean2 = context.getBean(PrototypeBean.class);

        System.out.println(bean1 == bean2); // 输出: false

        context.close();
    }
}

@Configuration
class AppConfig {
    @Bean
    @Scope("prototype")
    public MyPrototypeBean PrototypeBean() {
        return new PrototypeBean();
    }
}

class PrototypeBean {
   
}

在上述代码中,我们定义了PrototypeBean这一对象,同时将其注入到Spring容器中,并指定Scope的类型为prototype。然后,我们通过context.getBean来分别获取容器中的PrototypeBean对象,并比较两对象是否相等。

事实上,每次调用context.getBean(MyPrototypeBean.class)都会创建一个新的PrototypeBean实例,因此bean1bean2是不同的实例。

总结

本文深入探讨了Spring框架中SingletonBeanRegistry接口的作用和管理机制。其作为专门用于管理单例Bean的接口SingletonBeanRegistry提供了注册、获取和检查单例Bean的方法,使单例Bean的管理与其他Bean的管理功能解耦。进一步,SingletonBeanRegistry接口的引入,使得在Spring内部将单例Bean的管理功能抽象到SingletonBeanRegistry接口中,这让单例Bean的管理与其他Bean管理功能解耦。如果需要在不同的上下文中管理单例Bean,可以直接使用SingletonBeanRegistry接口,而不必依赖于整个BeanFactory接口。例如,一些轻量级的容器或模块可能只需要单例Bean管理功能,而不需要完整的Bean工厂功能,此时完全可以通过实现SingletonBeanRegistry接口来完成。

本文还解释了多例Bean的生命周期管理,展示了如何通过代码定义和获取多例Bean

相关推荐
鱟鲥鳚12 分钟前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
皮皮林55125 分钟前
开源实力派,给本地 AI 装上深度调研能力,一张 3090 跑到 95.7 分!
后端
努力的小雨1 小时前
把 Windows 桌面图标做成一个会自己运转的小世界
后端
武子康2 小时前
Search Console Platform Properties 扩大 SEO 资产边界:从 Page Ranking 到 Topic Coverage(5 类误读边界 + 3 表数据层设计)
前端·人工智能·后端
大模型码小白2 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司2 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地3 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
IT_陈寒3 小时前
Vue这个特性差点让我加班到凌晨,谁懂啊
前端·人工智能·后端
段一凡-华北理工大学4 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
码事漫谈4 小时前
1999年的电商前夜和2026年的AI前夜 历史押韵但从不重复
后端