欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

通過spring注解開發(fā),簡單測試單例和多例區(qū)別

 更新時間:2021年08月23日 10:42:13   作者:hz90s  
這篇文章主要介紹了通過spring注解開發(fā),簡單測試單例和多例區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

通過spring注解開發(fā),測試單例和多例區(qū)別

1.注解和配置兩種用法形式

配置版:

注解版:

2.在spring框架中,scope作用域默認是單例的

注:以下測試均是注解版

3.實例

(1)多例:

配置類:

@Configuration
public class PersonConfigure {
     //給容器中注冊一個bean,類型為返回值的類型,id為方法名
   @Scope("prototype") //多例
   @Bean()
   public Person person() {
        System.out.println("bean被加載到容器中");
     return new Person("張三",23);
   }
}

單元測試:

@Test
public void test02() {
     AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PersonConfigure.class);
     System.out.println("ioc容器加載完成");
     Person bean = (Person) context.getBean("person");
     bean.setName("lisi");
     System.out.println(bean.toString());
     Person bean1 = (Person) context.getBean("person");
     System.out.println(bean1.toString());
     System.out.println(bean==bean1);
}
}

測試結果:

結論:多例情況下,容器創(chuàng)建完成時不調用方法創(chuàng)建對象到容器中,在程序中獲取時,才會將對象加載到容器中,而且每次調用生成的都是不同的對象。

(2)單例(注解版)

配置類:

//默認是單例
@Configuration
public class PersonConfigure {
     //給容器中注冊一個bean,類型為返回值的類型,id為方法名
   @Bean()
   public Person person() {
    System.out.println("bean被加載到容器中");
     return new Person("張三",23);
   }
}

單元測試:

@Test
public void test02() {
     AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PersonConfigure.class);
     System.out.println("ioc容器加載完成");
     Person bean = (Person) context.getBean("person");
     bean.setName("lisi");
     System.out.println(bean.toString());
     Person bean1 = (Person) context.getBean("person");
     System.out.println(bean1.toString());
     System.out.println(bean==bean1);
}
}

測試結果:

結論:單例情況下,容器創(chuàng)建時調用方法創(chuàng)建對象到容器中,在程序中調用bean,直接從容器中拿取,且每次拿取的都是同一個對象。如果上一次對bean里的屬性做了修改,那下一次拿取的就是修改過的bean。

Spring中單例和多例的理解

1、什么是單例和多例

單例:所有請求用同一個對象來處理。通過單例模式,可以保證系統(tǒng)中一個類只有一個實例。

多例:每個請求用一個新的對象來處理。

2、Spring中的單例與多例

spring ioc容器的bean都是默認單例的,即spring依賴注入Bean實例默認是單例的。

spring提供了5中scope,分別是singleton,prototype,request,session,global session,常用是前兩種。點此查看官網(wǎng)介紹。

單例bean與多例(原型)bean的區(qū)別:

如果一個bean被聲明為單例的時候,在處理多次請求的時候,在spring容器里只實例化出一個bean,后續(xù)的請求都公用這個對象,這個對象會保存在一個map里面。當有請求來的時候,會先從緩存(map)里查看有沒有,有的話直接使用這個對象,沒有的話才實例化一個新的對象,所以這是個單例的。但是對于原型(prototype)bean來說,當每次請求來的時候,會直接實例化新的bean,沒有緩存以及緩存查詢的過程。

3、單例的優(yōu)勢與劣勢

優(yōu)勢:

由于不會創(chuàng)建新的對象,所以有以下幾個性能上的優(yōu)勢:

減少新生成實例的消耗。新生成實例包括兩個方面,第一,spring會通過反射或者cglib來生成bean實例,這都是耗性能的操作。第二,給對象分配內(nèi)存也會涉及負責算法。

減少jvm垃圾回收。由于不會給每個請求都生成bean實例,所以回收的對象就少了。

可以快速獲取到bean。因為單例獲取bean操作,除了第一次生成之外,其余都是從緩存里獲取的,所以很快。

劣勢:

一個很大的劣勢是它不能做到線程安全。由于所有請求都共享一個bean實例,那么如果這個bean是一個有狀態(tài)的bean的話,在并發(fā)場景下就有可能出現(xiàn)問題。

4、spring單例模式與線程安全:

當多用戶同時請求一個服務時,容器會給每一個請求分配一個線程,這時多個線程會并發(fā)執(zhí)行該請求所對應的業(yè)務邏輯(成員方法),此時就要注意了,如果該處理邏輯中有對該單例狀態(tài)的修改(體現(xiàn)為該單例的成員屬性),則必須考慮線程同步問題(此時該狀態(tài)就是一個臨界資源(共享數(shù)據(jù)),如果多個線程同時操作(修改)這個臨界資源就會誘發(fā)線程安全問題)。

線程安全:如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行的結果和單線程運行的結果是一樣的,而且其他的變量的值也和預期的是一樣的,就是線程安全的。或者說:一個類或者程序所提供的接口對于線程來說是原子操作,或者多線程之間的切換不會導致該接口的執(zhí)行結果存在二義性,就是線程安全的。

線程安全問題都是由全局變量及靜態(tài)變量引起的。

若每個線程中對全局變量,靜態(tài)變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的;若多個線程同時執(zhí)行寫操作,一般都需要考慮線程同步,否則就可能影響線程安全。

常量始終是線程安全的,因為只存在讀操作;

每次調用方法前都新建一個實例是線程安全的,因為不會訪問共享的資源;

局部變量是線程安全的。因為每執(zhí)行一個方法,都會在獨立的空間創(chuàng)建局部變量,它不是共享資源。局部變量包括方法的參數(shù)變量和方法內(nèi)的變量。

在關于spring單例與線程安全的很多文章中,會提到一個概念,即有狀態(tài)bean和無狀態(tài)bean。

  • 無狀態(tài)bean:無狀態(tài),就是一次操作,不能保存數(shù)據(jù)。無狀態(tài)bean,就是沒有實例變量的對象,不能保存數(shù)據(jù),是不變類,在線程安全的。
  • 有狀態(tài)bean:有狀態(tài),就是有數(shù)據(jù)存儲功能。有狀態(tài)bean,就是有實例變量的對象,可以保存數(shù)據(jù),是非線程安全的。

如何解決線程安全問題?

(1)使用線程同步機制:通過對象的鎖機制保證同一時間只有一個線程訪問變量。這時該變量是多個線程共享的,使用同步機制要求程序縝密地分析什么時候對變量進行讀寫,什么時候需要鎖定某個對象,什么時候釋放對象鎖等繁雜問題,程序設計和編寫難度相對較大。

(2)使用ThreadLocal:為每一個線程提供一個獨立的變量副本,從而隔離了多個線程對數(shù)據(jù)的訪問沖突。因為每一個線程都擁有自己的變量副本,從而也就沒有必要對該變量進行同步了。

概括起來就是:對于多線程資源共享的問題,同步機制采用了“以時間換空間”的方式,而ThreadLocal采用了“以空間換時間”的方式。前者僅提供一份變量,讓不同的線程排隊訪問,而后者為每一個線程都提供了一份變量,因此可以同時訪問而互不影響。

5、單例如何變多例

Scope聲明為prototype,即

@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Java中Set&List的迭代器實現(xiàn)步驟解析

    Java中Set&List的迭代器實現(xiàn)步驟解析

    這篇文章主要介紹了Java中Set&List的迭代器實現(xiàn)步驟解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • 在?Spring?Boot?中使用?Quartz?調度作業(yè)的示例詳解

    在?Spring?Boot?中使用?Quartz?調度作業(yè)的示例詳解

    這篇文章主要介紹了在?Spring?Boot?中使用?Quartz?調度作業(yè)的示例詳解,在本文中,我們將看看如何使用Quartz框架來調度任務,Quartz支持在特定時間運行作業(yè)、重復作業(yè)執(zhí)行、將作業(yè)存儲在數(shù)據(jù)庫中以及Spring集成,需要的朋友可以參考下
    2022-07-07
  • Spring Bean生命周期之Bean的實例化詳解

    Spring Bean生命周期之Bean的實例化詳解

    這篇文章主要為大家詳細介紹了Spring Bean生命周期之Bean的實例化,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • Jmeter邏輯控制器事務控制器使用方法解析

    Jmeter邏輯控制器事務控制器使用方法解析

    這篇文章主要介紹了Jmeter邏輯控制器事務控制器使用方法解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • SpringBoot @ExceptionHandler與@ControllerAdvice異常處理詳解

    SpringBoot @ExceptionHandler與@ControllerAdvice異常處理詳解

    在Spring Boot應用的開發(fā)中,不管是對底層數(shù)據(jù)庫操作,對業(yè)務層操作,還是對控制層操作,都會不可避免的遇到各種可預知的,不可預知的異常需要處理,如果每個處理過程都單獨處理異常,那么系統(tǒng)的代碼耦合度會很高,工作量大且不好統(tǒng)一,以后維護的工作量也很大
    2022-10-10
  • IDEA設置生成帶注釋的getter和setter的圖文教程

    IDEA設置生成帶注釋的getter和setter的圖文教程

    通常我們用idea默認生成的getter和setter方法是不帶注釋的,當然,我們同樣可以設置idea像MyEclipse一樣生成帶有Javadoc的模板,具體設置方法,大家參考下本文
    2018-05-05
  • Java創(chuàng)建ZIP壓縮文件的方法

    Java創(chuàng)建ZIP壓縮文件的方法

    這篇文章主要介紹了Java創(chuàng)建ZIP壓縮文件的方法,實例分析了java創(chuàng)建zip文件的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • JAVA編程不能不知道的反射用法總結

    JAVA編程不能不知道的反射用法總結

    這篇文章主要介紹了Java反射技術原理與用法,結合實例形式分析了Java反射技術的基本概念、功能、原理、用法及操作注意事項,需要的朋友可以參考下
    2021-07-07
  • 對Java字符串與整形、浮點類型之間的相互轉換方法總結

    對Java字符串與整形、浮點類型之間的相互轉換方法總結

    今天小編就為大家分享一篇對Java字符串與整形、浮點類型之間的相互轉換方法總結,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • SpringBoot項目的測試類實例解析

    SpringBoot項目的測試類實例解析

    這篇文章主要介紹了SpringBoot項目的測試類實例解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12

最新評論