Spring中的@Scope注解詳細(xì)講解及示例
1.@Scope注解是什么
@Scope注解是 Spring IOC 容器中的一個(gè)作用域,在 Spring IOC 容器中,他用來配置Bean實(shí)例的作用域?qū)ο蟆?/p>
@Scope 具有以下幾種作用域:
- singleton 單實(shí)例的(單例)(默認(rèn)) ----全局有且僅有一個(gè)實(shí)例
- prototype 多實(shí)例的(多例) ---- 每次獲取Bean的時(shí)候會有一個(gè)新的實(shí)例
- reqeust 同一次請求 ----request:每一次HTTP請求都會產(chǎn)生一個(gè)新的bean,同時(shí)該bean僅在當(dāng)前HTTP request內(nèi)有效
- session 同一個(gè)會話級別 ---- session:每一次HTTP請求都會產(chǎn)生一個(gè)新的bean,同時(shí)該bean僅在當(dāng)前HTTP session內(nèi)有效
注:這邊只演示我們常用的 singleton、prototype 兩種,其他的可以自己試試
2.@Scope注解怎么使用
直接在bean對象方法上增加@Scope注解即可。
① 在不指定@Scope的情況下,所有的bean都是單實(shí)例的bean,而且是餓漢模式加載(容器啟動實(shí)例就創(chuàng)建好了)
@Bean public Person person() { return new Person(); }
②指定@Scope為 prototype 表示為多實(shí)例的,而且還是懶漢模式加載(IOC容器啟動的時(shí)候,并不會創(chuàng)建對象,而是 在第一次使用的時(shí)候才會創(chuàng)建)
@Bean @Scope(value = "prototype") public Person person() { return new Person(); }
3.singleton/prototype模式演示
/** * Person類 */ public class Person { // Person類無參構(gòu)造方法 public Person() { System.out.println("執(zhí)行Person構(gòu)造器創(chuàng)建Person對象"); } }
/** * TODO 主配置類 * * @author : lzb * @date: 2021-03-05 13:50 */ @Configuration public class BeanConfig { @Bean @Scope(value = "singleton") public Person person(){ return new Person(); } }
3.1 singleton單例演示
@Scope注解默認(rèn)為singleton單例,singleton實(shí)例的意思不管你使用多少次在springIOC容器中只會存在一個(gè)實(shí)例,演示如下只打印了一次創(chuàng)建實(shí)例:
public class DemoApplication { public static void main(String[] args) { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class); Person person = ac.getBean(Person.class); Person person2 = ac.getBean(Person.class); System.out.println(person); System.out.println(person2); System.out.println(person == person2); } }
執(zhí)行結(jié)果:
可以發(fā)現(xiàn)singleton單例模式,在IOC容器中只會有一個(gè)實(shí)例存在,每次getBean()獲取的實(shí)例對象都是同一個(gè)。
3.2 prototype多例演示
/** * TODO 主配置類 * * @author : lzb * @date: 2021-03-05 13:50 */ @Configuration public class BeanConfig { @Bean @Scope(value = "prototype") public Person person(){ return new Person(); } }
執(zhí)行結(jié)果:
發(fā)現(xiàn)prototype多例模式,每次在調(diào)用getBean() 獲取實(shí)例時(shí),都會重新調(diào)用 Person 類的無參構(gòu)造方法,重新創(chuàng)建一個(gè) Person 對象。
4.惡漢/懶漢
使用singleton單例,采用餓漢加載(容器啟動,Bean實(shí)例就創(chuàng)建好了)
使用prototype多例,采用懶漢加載(IOC容器啟動的時(shí)候,并不會創(chuàng)建對象實(shí)例,而是在第一次使用的時(shí)候才會創(chuàng)建)
4.1 singleton 惡漢
演示
/** * TODO 主配置類 * * @author : lzb * @date: 2021-03-05 13:50 */ @Configuration public class BeanConfig { @Bean @Scope(value = "singleton") public Person person(){ return new Person(); } }
public class DemoApplication { public static void main(String[] args) { // 啟動Spring IOC容器 AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class); } }
執(zhí)行結(jié)果:
singleton單例模式,在 IOC 容器啟動時(shí),便會去調(diào)用 Person 類的無參構(gòu)造方法,創(chuàng)建一個(gè) Person 對象。此時(shí)并沒有調(diào)用 getBean() 方法來獲取Person 對象實(shí)例。
所以singleton 采用的是 惡漢式 創(chuàng)建實(shí)例對象
注:如何將 singleton 單例模式的 惡漢式 變更為 懶漢式,只需要再添加一個(gè) @Lazy 注解即可。 如下所示:
@Configuration public class BeanConfig { @Bean @Scope @Lazy public Person person(){ return new Person(); } }
4.2 prototype 懶漢
演示
/** * TODO 主配置類 * * @author : lzb * @date: 2021-03-05 13:50 */ @Configuration public class BeanConfig { @Bean @Scope(value = "prototype") public Person person(){ return new Person(); } }
public class DemoApplication { public static void main(String[] args) { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class); System.out.println("=================IOC容器啟動成功=============="); Person person = ac.getBean(Person.class); System.out.println(person); } }
執(zhí)行結(jié)果:
prototype多例模式,在 IOC 容器啟動時(shí),并不會去創(chuàng)建Bean實(shí)例,只有在調(diào)用 getBean() 方法獲取Person 對象時(shí),才會去調(diào)用 Person 類的無參構(gòu)造方法,創(chuàng)建一個(gè) Person 對象。
所以 prototype 采用的是 懶漢式 創(chuàng)建實(shí)例對象
5.Bean實(shí)例對象的銷毀
針對單實(shí)例bean的話,容器啟動的時(shí)候,bean的對象就創(chuàng)建了,而且容器銷毀的時(shí)候,也會調(diào)用Bean的銷毀方法;
針對多實(shí)例bean的話,容器啟動的時(shí)候,bean是不會被創(chuàng)建的而是在獲取bean的時(shí)候被創(chuàng)建,而且bean的銷毀不受IOC容器的管理,是由GC來處理的
針對每一個(gè)Bean實(shí)例,都會有一個(gè)initMethod() 和 destroyMethod() 方法,我們可以在Bean 類中自行定義,也可以使用 Spring 默認(rèn)提供的這兩個(gè)方法。
public class Person { public Person() { System.out.println("執(zhí)行Person構(gòu)造器創(chuàng)建Person對象"); } public void init() { System.out.println("initMethod"); } public void destroy() { System.out.println("destroyMethod"); } }
@Configuration public class BeanConfig { @Bean(initMethod = "init", destroyMethod = "destroy") // 可以自己指定方法名,也可以不指定,使用Spring默認(rèn)提供的方法 @Scope(value = "singleton") public Person person(){ return new Person(); } }
singleton單例,在IOC容器銷毀時(shí),就會調(diào)用 destroyMethod() 方法來將 Bean對象銷毀;prototype多例,它的Bean實(shí)例對象則不受IOC容器的管理,最終由GC來銷毀。
6.@Scope注解的使用場景
幾乎90%以上的業(yè)務(wù)使用 singleton單例就可以,所以 Spring 默認(rèn)的類型也是singleton,singleton雖然保證了全局是一個(gè)實(shí)例,對性能有所提高,但是如果實(shí)例中有非靜態(tài)變量時(shí),會導(dǎo)致線程安全問題,共享資源的競爭。
當(dāng)設(shè)置為prototype多例時(shí):每次連接請求,都會生成一個(gè)bean實(shí)例,也會導(dǎo)致一個(gè)問題,當(dāng)請求數(shù)越多,性能會降低,因?yàn)閯?chuàng)建的實(shí)例,導(dǎo)致GC頻繁,GC時(shí)長增加。
到此這篇關(guān)于Spring中的@Scope注解詳細(xì)講解及示例的文章就介紹到這了,更多相關(guān)Spring中的@Scope注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
將JavaWeb項(xiàng)目部署到云服務(wù)器的詳細(xì)步驟
這篇文章主要介紹了將JavaWeb項(xiàng)目部署到云服務(wù)器的詳細(xì)步驟,文章通過圖文結(jié)合的方式給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-12-12springboot解決Class path contains multiple 
這篇文章主要介紹了springboot解決Class path contains multiple SLF4J bindings問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07Java讀寫pdf文件的詳細(xì)實(shí)現(xiàn)方法
最近公司的項(xiàng)目中需要操作pdf文件,所以這里給大家總結(jié)下方法,這篇文章主要給大家介紹了關(guān)于Java讀寫pdf文件的詳細(xì)實(shí)現(xiàn)方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09NameNode?重啟恢復(fù)數(shù)據(jù)的流程詳解
這篇文章主要為大家介紹了NameNode?重啟恢復(fù)數(shù)據(jù)的流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02SpringBoot數(shù)據(jù)校驗(yàn)功能的實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot數(shù)據(jù)校驗(yàn)功能的實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02使用kotlin編寫spring cloud微服務(wù)的過程
這篇文章主要介紹了使用kotlin編寫spring cloud微服務(wù)的相關(guān)知識,本文給大家提到配置文件的操作代碼,給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09Spring-boot 2.3.x源碼基于Gradle編譯過程詳解
這篇文章主要介紹了Spring-boot 2.3.x源碼基于Gradle編譯過程詳解,本文通過實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12SpringBoot Maven打包插件spring-boot-maven-plugin無法解析原因
spring-boot-maven-plugin是spring boot提供的maven打包插件,本文主要介紹了SpringBoot Maven打包插件spring-boot-maven-plugin無法解析原因,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03java學(xué)生管理系統(tǒng)界面簡單實(shí)現(xiàn)(全)
這篇文章主要為大家詳細(xì)介紹了java學(xué)生管理系統(tǒng)界面的簡單實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01