日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Spring中的單例模式應用詳解

作者:搬磚的小熊貓 更新時間: 2024-07-15 編程語言

1. DefaultListableBeanFactory

在Spring中,所有由Spring容器管理的Bean默認都是單例的。Spring框架中最經典的單例模式實現是在BeanFactory中。BeanFactory是Spring IoC容器的核心接口,其實現類DefaultListableBeanFactory在加載Bean定義時,會將單例的Bean實例化并緩存在ConcurrentHashMap中,以保證該Bean的唯一性。

在這里插入圖片描述

DefaultListableBeanFactory定義了三個Map對象:singletonObjects、singletonFactories和earlySingletonObjects,它們都被設計為線程安全的ConcurrentHashMap。

  • singletonObjects用于存儲已經實例化的單例Bean對象。
  • singletonFactories用于存儲BeanFactory對象。
  • earlySingletonObjects用于存儲未完全初始化的Bean對象。

當一個單例Bean實例被獲取時,DefaultListableBeanFactory會首先檢查singletonObjects是否存在該Bean實例,如果存在則直接返回,否則就從earlySingletonObjects或singletonFactories中獲取或創建該Bean實例。

2. SingletonBeanRegistry

單例相關的操作其實是被定義在SingletonBeanRegistry接口中。SingletonBeanRegistry是Spring框架中的一個接口,定義了向Spring IoC容器中添加和獲取單例Bean的方法。

在這里插入圖片描述

public interface SingletonBeanRegistry {

    // 將指定名稱的Bean實例注冊為單例Bean。如果該名稱已經存在于單例Bean注冊表中,則會拋出IllegalStateException異常。
    void registerSingleton(String var1, Object var2);

    // 獲取指定名稱的單例Bean實例。如果指定名稱的Bean實例不存在,則返回null。
    @Nullable
    Object getSingleton(String var1);

    // 檢查指定名稱的單例Bean實例是否已經存在于單例Bean注冊表中。
    boolean containsSingleton(String var1);

    // 獲取所有已注冊的單例Bean名稱。
    String[] getSingletonNames();

    // 獲取當前容器中已經注冊的單例Bean的數量。
    int getSingletonCount();

    // 獲取一個用于同步單例Bean注冊表的對象。
    Object getSingletonMutex();
}

3. Spring單例Bean與單例模式的區別

Spring單例Bean與單例模式的區別在于它們關聯的環境不一樣,單例模式是指在一個JVM進程中僅有一個實例,而Spring單例是指一個Spring Bean容器(ApplicationContext)中僅有一個實例。

首先看單例模式,在一個JVM進程中(理論上,一個運行的JAVA程序就必定有自己一個獨立的JVM)僅有一個實例,無論在程序中的何處獲取實例,始終都返回同一個對象。以Java內置的Runtime為例,下面的判斷始終為真:

// 在一個JVM實例中始終只有一個實例
Runtime.getRuntime() == Runtime.getRuntime();

與此相比,Spring的單例Bean是與其容器 ApplicationContext密切相關的,所以在一個JVM進程中,如果有多個Spring容器,即使是單例bean,也一定會創建多個實例,代碼示例如下:

public static void main(String[] args) {

    System.out.println(Runtime.getRuntime() == Runtime.getRuntime());

    // 第一個Spring Bean容器
    ClassPathXmlApplicationContext context_1 = new ClassPathXmlApplicationContext("bean.xml");
    Person msb1 = context_1.getBean("person", Person.class);

    // 第二個Spring Bean容器
    ClassPathXmlApplicationContext context_2 = new ClassPathXmlApplicationContext("bean.xml");
    Person msb2 = context_2.getBean("person", Person.class);

    // 這里絕對不會相等,因為創建了多個實例
    System.out.println(msb1 == msb2);
}

以下是Spring的配置文件:

<!-- 即使聲明了為單例,只要有多個容器,也一定會創建多個實例 -->
<bean id="person" class="com.mashibing.spring01.demo03.Person" scope="singleton">
    <constructor-arg name="username">
        <value>mashibing</value>
    </constructor-arg>
</bean>

如果不指定bean的類型,Spring框架生成的Bean默認就是單例的(在當前容器里)。

Spring的單例Bean與Spring Bean管理容器密切相關,每個容器都會創建自己獨有的實例,所以與GOF設計模式中的單例模式相差極大,但在實際應用中,如果將對象的生命周期完全交給Spring管理(不在其他地方通過new、反射等方式創建),其實也能達到單例模式的效果。

原文鏈接:https://blog.csdn.net/qq_26893655/article/details/140337231

  • 上一篇:沒有了
  • 下一篇:沒有了
欄目分類
最近更新