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

Spring?Bean的作用域具體實(shí)現(xiàn)(單例、多例、請(qǐng)求、會(huì)話、Application)

 更新時(shí)間:2025年08月06日 10:52:02   作者:椰椰椰耶  
文章講解了Spring?IoC/?DI中Bean作用域的管理方式,涵蓋單例(singleton)、原型(prototype)及Web環(huán)境的request、session、application作用域,通過(guò)注解和配置區(qū)分不同作用域的實(shí)例創(chuàng)建規(guī)則,并通過(guò)測(cè)試驗(yàn)證其生命周期與共享特性,感興趣的朋友一起看看吧

概念

Spring Ioc&DI 戒斷,我們學(xué)習(xí)了 Spring 是如何幫助我們管理對(duì)象的

  1. 通過(guò) @Controller,@Service@Repository,@Component,@Configuration@Bean 來(lái)聲明 Bean 對(duì)象
  2. 通過(guò) ApplicationContext 或者 BeanFactory 來(lái)獲取對(duì)象
  3. 通過(guò) @Autowired,Setter 方法或者構(gòu)造方法等來(lái)為應(yīng)用程序注入所依賴的 Bean 對(duì)象

我們來(lái)簡(jiǎn)單回顧一下

  1. 通過(guò) @Bean 聲明 bean,把 bean 存在 Spring 容器中
public class Dog {  
    private String name;  
    public void setName(String name) {  
        this.name = name;  
    }  
}
@Component  
public class DogBeanConfig {  
    @Bean  
    public Dog dog() {  
        Dog dog = new Dog();  
        dog.setName("旺旺");  
        return dog;  
    }  
}
  1. Spring 容器中獲取 Bean
    • 通過(guò)在代碼中直接注入 ApplicationContext 的方式
@SpringBootTest  
class ApplicationTests {  
    @Autowired  
    private ApplicationContext applicationContext;  
    @Test  
    void contextLoads() {  
        DogBeanConfig dog1 = applicationContext.getBean(DogBeanConfig.class);;  
        System.out.println(dog1);  
    }  
}

司改代碼,從 Spring 容器中多次獲取 Bean

@SpringBootTest  
class ApplicationTests {  
    @Autowired  
    private ApplicationContext applicationContext;  
    @Test  
    void contextLoads() {  
        DogBeanConfig dog1 = applicationContext.getBean(DogBeanConfig.class);;  
        System.out.println(dog1);  
        DogBeanConfig dog2 = applicationContext.getBean(DogBeanConfig.class);;  
        System.out.println(dog2);  
    }  
}

觀察運(yùn)行結(jié)果

發(fā)現(xiàn)輸出的 bean 對(duì)象地址是一樣的,說(shuō)明每次從 Spring 容器中取出來(lái)的對(duì)象都是同一個(gè)

  • 這也是“單例模式
  • 單例模式:確保一個(gè)類只有一個(gè)實(shí)例,多次創(chuàng)建也不會(huì)創(chuàng)建出多個(gè)實(shí)例

Bean 的作用域是值 BeanSpring 框架中的某種行為模式

比如單例作用域:表示 Bean 在整個(gè) Spring 中只有一份,它是全局共享的。那么當(dāng)其他人修改了這個(gè)值之后,那么另一個(gè)人讀到的就是被修改后的值

修改上述代碼,給 UserController 添加屬性 name

@SpringBootTest  
class ApplicationTests {  
    @Autowired  
    private ApplicationContext applicationContext;  
    @Test  
    void contextLoads() {  
        Dog dog1 = applicationContext.getBean(Dog.class);  
        dog1.setName("狗狗1");  
        System.out.println(dog1);  
        System.out.println(dog1.getName());  
        Dog dog2 = applicationContext.getBean(Dog.class);;  
        System.out.println(dog2);  
        System.out.println(dog2.getName());  
    }  
}

觀察運(yùn)行結(jié)果:

  • dog1dog2 為同一個(gè)對(duì)象,dog2 拿到了 dog1 設(shè)置的值

那能不能將 bean 對(duì)象設(shè)置為非單例的(每次獲取的 bean 都是一個(gè)新對(duì)象呢)

  • 這就是 Bean 的不同作用域了

Bean 的作用域

Spring 中支持 6 中作用域,后 4 種在 Spring MVC 環(huán)境才生效

  1. singleton:?jiǎn)卫饔糜?
    • 每個(gè) Spring Ioc 容器內(nèi)同名稱的 Bean 只有一個(gè)實(shí)例(單例)(默認(rèn))
  2. prototype:原型作用域(多例作用域)
    • 每次使用該 bean 時(shí)會(huì)創(chuàng)建新的實(shí)例(非單例)
  3. request:請(qǐng)求作用域
    • 每個(gè) HTTP 請(qǐng)求生命周期內(nèi),創(chuàng)建新的實(shí)例(Web 環(huán)境中,了解)
  4. session:會(huì)話作用域
    • 每個(gè) HTTP Session 生命周期內(nèi),創(chuàng)建新的實(shí)例(Web 環(huán)境中,了解)
  5. Application:全局作用域
    • 每個(gè) ServletContext 生命周期里內(nèi),創(chuàng)建新的實(shí)例(web 環(huán)境中,了解)
  6. websocketHTTP WebSocket 作用域
    • 每個(gè) WebSocket 生命周期內(nèi),創(chuàng)建新的實(shí)例(web 環(huán)境中,了解)

我們來(lái)看簡(jiǎn)單的代碼實(shí)現(xiàn)

定義幾個(gè)不同作用域的 bean

@Component  
public class DogBeanConfig {  
    @Bean  
    public Dog dog() {  
        Dog dog = new Dog();  
        dog.setName("旺旺");  
        return dog;  
    }  
    @Bean  
    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)  
    public Dog singleDog() {  
        Dog dog = new Dog();  
        return dog;  
    }  
    @Bean  
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)  
    public Dog prototype() {  
        Dog dog = new Dog();  
        return dog;  
    }  
    @Bean  
    @RequestScope    
    public Dog requestDog() {  
        Dog dog = new Dog();  
        return dog;  
    }  
    @Bean  
    @SessionScope    
    public Dog sessionDog() {  
        Dog dog = new Dog();  
        return dog;  
    }  
    @Bean  
    @ApplicationScope    
    public Dog applicationDog() {  
        Dog dog = new Dog();  
        return dog;  
    }  
}
  • @RequestScope 等同于 @Scope (value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
  • @SessionScope 等同于 @Scope (value =WebApplicationContext.SCOPE_SESSION, proxyMode =ScopedProxyMode.TARGET_CLASS)
  • @ApplicationScope 等同于 @Scope (value =WebApplicationContext. SCOPE_APPLICATION, proxyMode =ScopedProxyMode. TARGET_CLASS)

proxyMode ?來(lái)為 springbean 設(shè)置代理 .proxyMode = ScopedProxyMode.TARGET_CLASS 表?這個(gè) Bean 基于 CGLIB 實(shí)現(xiàn)動(dòng)態(tài)代理,Request,sessionapplication 作?域的 Bean 需要設(shè)置 proxyMode

代碼測(cè)試

測(cè)試不同作用域的 bean 取到的對(duì)象是否一樣

@RestController  
public class DogController {  
    @Autowired  
    private Dog singleDog;  
    @Autowired  
    private Dog prototypeDog;  
    @Autowired  
    private Dog requestDog;  
    @Autowired  
    private Dog sessionDog;  
    @Autowired  
    private Dog applicationDog;  
    @Autowired  
    private ApplicationContext applicationContext;  
    @RequestMapping("/single")  
    public String single(){  
        Dog contexDog = (Dog) applicationContext.getBean("singleDog");  
        return "dog: " + singleDog.toString() + ", contextDog: " + contexDog;  
    }  
    @RequestMapping("/prototype")  
    public String prototype() {  
        Dog contextDog = (Dog) applicationContext.getBean("prototypeDog");  
        return "dog: " + prototypeDog.toString() + ", contextDog: " + contextDog;  
    }  
    @RequestMapping("/request")  
    public String request(){  
        Dog contexDog = (Dog) applicationContext.getBean("requestDog");  
        return "dog: " + requestDog.toString() + ", contextDog: " + contexDog;  
    }  
    @RequestMapping("/session")  
    public String session() {  
        Dog contextDog = (Dog) applicationContext.getBean("sessionDog");  
        return "dog: " + sessionDog.toString() + ", contextDog: " + contextDog;  
    }  
    @RequestMapping("/application")  
    public String application() {  
        Dog contextDog = (Dog) applicationContext.getBean("applicationDog");  
        return "dog: " + applicationDog.toString() + ", contextDog: " + contextDog;  
    }  
}
  • 每個(gè)請(qǐng)求都獲取兩次 Bean
  • @AutowiredapplicationContext.getBean("singleDog") 都是從 Spring 容器中獲取對(duì)象

觀察 Bean 的作用域

1.單例作用域

地址: http://127.0.0.1:8080/single

多次訪問(wèn),得到的都是同一個(gè)對(duì)象,并且 @AutowiredapplicationContext.getBean() 也是同一個(gè)對(duì)象

2.多例作用域

地址: http://127.0.0.1:8080/prototype

觀察 ContextDog,每次獲取的對(duì)象都不一樣(注入的對(duì)象在 Spring 容器啟動(dòng)時(shí),就已經(jīng)注入了,所以多次請(qǐng)求訪問(wèn)也不會(huì)發(fā)生變化)

3.請(qǐng)求作用域

地址: http://127.0.0.1:8080/request

在一次請(qǐng)求中,@AutowiredapplicationContext.getBean() 也是同一個(gè)對(duì)象,但是每次請(qǐng)求,都會(huì)重新創(chuàng)建對(duì)象

4.會(huì)話作用域

地址: http://127.0.0.1:8080/session

在一個(gè) session 中,多次請(qǐng)求,獲取到的對(duì)象都是同一個(gè)

換一個(gè)瀏覽器訪問(wèn),發(fā)現(xiàn)會(huì)重新創(chuàng)建對(duì)象(另一個(gè) session

5.Application作用域

地址: http://127.0.0.1:8080/application

在一個(gè)應(yīng)用中,多次訪問(wèn)都是同一個(gè)對(duì)象

  • Application scope 就是對(duì)于整個(gè) web 容器來(lái)說(shuō),bean 的作用域是 ServletContext 級(jí)別的
  • 這個(gè)和 singleton 有點(diǎn)類似,區(qū)別在于:Application scopeServletContext 的單例,singleton 是一個(gè) ApplicationContext 的單例
  • 在一個(gè) web 容器中 ApplicationContext 可以有多個(gè)(了解即可)

到此這篇關(guān)于Spring Bean的作用域具體實(shí)現(xiàn)(單例、多例、請(qǐng)求、會(huì)話、Application)的文章就介紹到這了,更多相關(guān)Spring Bean作用域內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot下實(shí)現(xiàn)RedisTemplate?List?清空

    springboot下實(shí)現(xiàn)RedisTemplate?List?清空

    我們經(jīng)常會(huì)使用Redis的List數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)一系列的元素,當(dāng)我們需要清空一個(gè)List時(shí),可以使用RedisTemplate來(lái)實(shí)現(xiàn),本文就來(lái)詳細(xì)的介紹一下如何實(shí)現(xiàn),感興趣的可以了解一下
    2024-01-01
  • 示例解析java重載Overloading與覆蓋Overriding

    示例解析java重載Overloading與覆蓋Overriding

    這篇文章主要介紹了java重載Overloading與覆蓋Overriding的示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • 非常全面的Java異常處理(全文干貨,值得收藏)

    非常全面的Java異常處理(全文干貨,值得收藏)

    這篇文章主要給大家介紹了非常全面的Java異常處理的相關(guān)資料,全文干貨,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 深入分析Spring BeanDefinition的構(gòu)造元信息

    深入分析Spring BeanDefinition的構(gòu)造元信息

    Bean Definition是一個(gè)包含Bean元數(shù)據(jù)的對(duì)象,它描述了如何創(chuàng)建Bean實(shí)例、Bean屬性的值以及Bean之間的依賴關(guān)系,本文將帶大家深入分析Spring BeanDefinition的構(gòu)造元信息,需要的朋友可以參考下
    2024-01-01
  • kafka添加安全驗(yàn)證配置方式

    kafka添加安全驗(yàn)證配置方式

    這篇文章主要介紹了kafka添加安全驗(yàn)證配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Java中的拷貝數(shù)組CopyOnWriteArrayList詳解

    Java中的拷貝數(shù)組CopyOnWriteArrayList詳解

    這篇文章主要介紹了Java中的拷貝數(shù)組CopyOnWriteArrayList詳解,ArrayList和LinkedList都不是線程安全的,如果需要線程安全的List,可以使用synchronizedList來(lái)生成一個(gè)同步list,但是這個(gè)同步list的方法都是通過(guò)synchronized修飾來(lái)保證同步的,需要的朋友可以參考下
    2023-12-12
  • Java如何根據(jù)word模板導(dǎo)出數(shù)據(jù)

    Java如何根據(jù)word模板導(dǎo)出數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)根據(jù)word模板導(dǎo)出數(shù)據(jù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-05-05
  • Spring中存儲(chǔ)Bean的常見(jiàn)注解方式

    Spring中存儲(chǔ)Bean的常見(jiàn)注解方式

    Spring框架中的控制反轉(zhuǎn)(IoC)和依賴注入(DI)是核心概念,實(shí)現(xiàn)了對(duì)象的解耦和動(dòng)態(tài)依賴,IoC容器負(fù)責(zé)對(duì)象的生命周期和對(duì)象間的依賴關(guān)系,通過(guò)DI方式注入依賴,本文介紹Spring中存儲(chǔ)Bean的常見(jiàn)注解方式,感興趣的朋友一起看看吧
    2024-09-09
  • SpringBoot如何利用Twilio?Verify發(fā)送驗(yàn)證碼短信

    SpringBoot如何利用Twilio?Verify發(fā)送驗(yàn)證碼短信

    Twilio提供了一個(gè)名為?Twilio?Verify?的服務(wù),專門(mén)用于處理驗(yàn)證碼的發(fā)送和驗(yàn)證,下面我們就來(lái)看看如何使用Twilio?Verify實(shí)現(xiàn)發(fā)送驗(yàn)證碼短信吧
    2025-03-03
  • Java獲取當(dāng)前時(shí)間方法總結(jié)

    Java獲取當(dāng)前時(shí)間方法總結(jié)

    本篇文章給大家整理了關(guān)于Java獲取當(dāng)前時(shí)間方法,以及相關(guān)代碼分享,有需要的朋友測(cè)試參考下吧。
    2018-02-02

最新評(píng)論