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í)候會(huì)有一個(gè)新的實(shí)例
- reqeust 同一次請(qǐng)求 ----request:每一次HTTP請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的bean,同時(shí)該bean僅在當(dāng)前HTTP request內(nèi)有效
- session 同一個(gè)會(huì)話級(jí)別 ---- session:每一次HTTP請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的bean,同時(shí)該bean僅在當(dāng)前HTTP session內(nèi)有效
注:這邊只演示我們常用的 singleton、prototype 兩種,其他的可以自己試試
2.@Scope注解怎么使用
直接在bean對(duì)象方法上增加@Scope注解即可。
① 在不指定@Scope的情況下,所有的bean都是單實(shí)例的bean,而且是餓漢模式加載(容器啟動(dòng)實(shí)例就創(chuàng)建好了)
@Bean
public Person person() {
return new Person();
}
②指定@Scope為 prototype 表示為多實(shí)例的,而且還是懶漢模式加載(IOC容器啟動(dòng)的時(shí)候,并不會(huì)創(chuàng)建對(duì)象,而是 在第一次使用的時(shí)候才會(huì)創(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對(duì)象");
}
}
/**
* 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容器中只會(huì)存在一個(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容器中只會(huì)有一個(gè)實(shí)例存在,每次getBean()獲取的實(shí)例對(duì)象都是同一個(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í),都會(huì)重新調(diào)用 Person 類的無參構(gòu)造方法,重新創(chuàng)建一個(gè) Person 對(duì)象。
4.惡漢/懶漢
使用singleton單例,采用餓漢加載(容器啟動(dòng),Bean實(shí)例就創(chuàng)建好了)
使用prototype多例,采用懶漢加載(IOC容器啟動(dòng)的時(shí)候,并不會(huì)創(chuàng)建對(duì)象實(shí)例,而是在第一次使用的時(shí)候才會(huì)創(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) {
// 啟動(dòng)Spring IOC容器
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(BeanConfig.class);
}
}
執(zhí)行結(jié)果:

singleton單例模式,在 IOC 容器啟動(dòng)時(shí),便會(huì)去調(diào)用 Person 類的無參構(gòu)造方法,創(chuàng)建一個(gè) Person 對(duì)象。此時(shí)并沒有調(diào)用 getBean() 方法來獲取Person 對(duì)象實(shí)例。
所以singleton 采用的是 惡漢式 創(chuàng)建實(shí)例對(duì)象
注:如何將 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容器啟動(dòng)成功==============");
Person person = ac.getBean(Person.class);
System.out.println(person);
}
}
執(zhí)行結(jié)果:

prototype多例模式,在 IOC 容器啟動(dòng)時(shí),并不會(huì)去創(chuàng)建Bean實(shí)例,只有在調(diào)用 getBean() 方法獲取Person 對(duì)象時(shí),才會(huì)去調(diào)用 Person 類的無參構(gòu)造方法,創(chuàng)建一個(gè) Person 對(duì)象。
所以 prototype 采用的是 懶漢式 創(chuàng)建實(shí)例對(duì)象
5.Bean實(shí)例對(duì)象的銷毀
針對(duì)單實(shí)例bean的話,容器啟動(dòng)的時(shí)候,bean的對(duì)象就創(chuàng)建了,而且容器銷毀的時(shí)候,也會(huì)調(diào)用Bean的銷毀方法;
針對(duì)多實(shí)例bean的話,容器啟動(dòng)的時(shí)候,bean是不會(huì)被創(chuàng)建的而是在獲取bean的時(shí)候被創(chuàng)建,而且bean的銷毀不受IOC容器的管理,是由GC來處理的
針對(duì)每一個(gè)Bean實(shí)例,都會(huì)有一個(gè)initMethod() 和 destroyMethod() 方法,我們可以在Bean 類中自行定義,也可以使用 Spring 默認(rèn)提供的這兩個(gè)方法。
public class Person {
public Person() {
System.out.println("執(zhí)行Person構(gòu)造器創(chuàng)建Person對(duì)象");
}
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í),就會(huì)調(diào)用 destroyMethod() 方法來將 Bean對(duì)象銷毀;prototype多例,它的Bean實(shí)例對(duì)象則不受IOC容器的管理,最終由GC來銷毀。
6.@Scope注解的使用場(chǎng)景
幾乎90%以上的業(yè)務(wù)使用 singleton單例就可以,所以 Spring 默認(rèn)的類型也是singleton,singleton雖然保證了全局是一個(gè)實(shí)例,對(duì)性能有所提高,但是如果實(shí)例中有非靜態(tài)變量時(shí),會(huì)導(dǎo)致線程安全問題,共享資源的競(jìng)爭(zhēng)。
當(dāng)設(shè)置為prototype多例時(shí):每次連接請(qǐng)求,都會(huì)生成一個(gè)bean實(shí)例,也會(huì)導(dǎo)致一個(gè)問題,當(dāng)請(qǐng)求數(shù)越多,性能會(huì)降低,因?yàn)閯?chuàng)建的實(shí)例,導(dǎo)致GC頻繁,GC時(shí)長(zhǎng)增加。
到此這篇關(guān)于Spring中的@Scope注解詳細(xì)講解及示例的文章就介紹到這了,更多相關(guān)Spring中的@Scope注解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中自旋鎖與CAS機(jī)制的深層關(guān)系與區(qū)別
CAS算法即比較并替換,是一種實(shí)現(xiàn)并發(fā)編程時(shí)常用到的算法,Java并發(fā)包中的很多類都使用了CAS算法,這篇文章主要介紹了Java中自旋鎖與CAS機(jī)制深層關(guān)系與區(qū)別的相關(guān)資料,需要的朋友可以參考下2025-11-11
Java實(shí)現(xiàn)樹形菜單的方法總結(jié)
當(dāng)我們想要展示層級(jí)結(jié)構(gòu),如文件目錄、組織結(jié)構(gòu)或分類目錄時(shí),樹形菜單是一個(gè)直觀且有效的解決方案,本文為大家整理了java中幾種常見方法,希望對(duì)大家有所幫助2023-08-08
java多線程Synchronized實(shí)現(xiàn)可見性原理解析
這篇文章主要介紹了java多線程Synchronized實(shí)現(xiàn)可見性原理,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12
spring是如何實(shí)現(xiàn)聲明式事務(wù)的
這篇文章主要介紹了spring是如何實(shí)現(xiàn)聲明式事務(wù)的,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
SpringBoot中@Autowired與@Resource的區(qū)別小結(jié)
本文主要介紹了SpringBoot中@Autowired與@Resource的區(qū)別小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-01-01
Spring?myBatis數(shù)據(jù)庫連接異常問題及解決
這篇文章主要介紹了Spring?myBatis數(shù)據(jù)庫連接異常問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
Java實(shí)現(xiàn)二叉樹的示例代碼(遞歸&迭代)
二叉樹(Binary?tree)是樹形結(jié)構(gòu)的一個(gè)重要類型。本文將利用Java語言實(shí)現(xiàn)二叉樹,文中的示例代碼講解詳細(xì),需要的同學(xué)可以參考一下2022-03-03
Java 常用類解析:java異常機(jī)制,異常棧,異常處理方式,異常鏈,異常丟失詳解
這篇文章主要介紹了Java 常用類解析:java異常機(jī)制,異常棧,異常處理方式,異常鏈,異常丟失詳解的相關(guān)資料,需要的朋友可以參考下2017-03-03
Servlet注解之@WebInitParam多個(gè)InitParam的使用
這篇文章主要介紹了Servlet注解之@WebInitParam多個(gè)InitParam的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04

