最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring?框架中的?Bean?作用域(Scope)使用詳解

 更新時間:2023年09月12日 08:48:34   作者:god23bin  
Spring框架中的Bean作用域(Scope)決定了在應(yīng)用程序中創(chuàng)建和管理的Bean對象的生命周期和可見性。本文將詳細(xì)介紹Spring框架中的Bean作用域的不同類型,包括Singleton、Prototype、Request、Session和Application,并解釋它們的特點(diǎn)和適用場景。

什么是 Bean 的作用域?

我們在以 XML 作為配置元數(shù)據(jù)的情況下,進(jìn)行 Bean 的定義,是這樣的:

<bean id="vehicle" class="cn.god23bin.demo.domain.model.Vehicle">
	<!-- 協(xié)作者寫在這里... -->
</bean>

我們寫了一個 Bean 定義(Bean Definition),就是用于創(chuàng)建所定義的類的實(shí)例的。

一個 Bean 定義,我們可以類比一個類的定義,你定義了一個類,你可以根據(jù)這個類創(chuàng)建出許多實(shí)例對象。同理,Bean 定義也是,也是可以根據(jù)這個定義創(chuàng)建許多實(shí)例對象的,只不過這里是 Spring 幫我們創(chuàng)建,而不是我們手動 new 。 這些 Bean 對象實(shí)例,我們可以理解為 Spring IoC 容器中的對象。

在寫 Bean 定義的過程中,我們可以控制各種 Bean 的依賴項(xiàng)和相應(yīng)的值,將這些依賴項(xiàng)和值注入到 Bean 定義所創(chuàng)建的對象中。同理,這個過程也可以控制 Bean 定義創(chuàng)建的對象的 Scope(作用域)。Bean 的作用域定義了在容器中創(chuàng)建的 Bean 實(shí)例的生命周期以及在應(yīng)用程序中的可見性。

6 種 Bean 的作用域

Spring 支持 6 種 Bean 的作用域,其中有 4 種是在 Web 應(yīng)用下才能感知到的,如下表所示:

Scope說明
singleton(默認(rèn)情況下)每個 Spring IoC 容器將單個 Bean 定義的 Scope 指定為單個對象實(shí)例。
prototype將單個 Bean 定義的 Scope 擴(kuò)大到任意數(shù)量的對象實(shí)例。
request將單個 Bean 定義的 Scope 擴(kuò)大到單個 HTTP 請求的生命周期。也就是說,每個 HTTP 請求都有自己的 Bean 實(shí)例,該實(shí)例是在單個 Bean 定義的基礎(chǔ)上創(chuàng)建的。只在 Web 感知的 Spring ApplicationContext 的上下文中有效。
session將單個 Bean 定義的 Scope 擴(kuò)大到一個 HTTP 會話的生命周期。只在 Web 感知的 Spring ApplicationContext 的上下文中有效。
application將單個 Bean 定義的 Scope 擴(kuò)大到 ServletContext 的生命周期中。只在 Web 感知的 Spring ApplicationContext 的上下文中有效。
websocket將單個 Bean 定義的 Scope 擴(kuò)大到 WebSocket 的生命周期。只在 Web 感知的 Spring ApplicationContext 的上下文中有效。

1. Singleton Scope

singleton 作用域的 Bean,在 Spring IoC 容器中就有且僅有一個該類型的實(shí)例對象,也就是單例的。

默認(rèn)情況下,我們在寫 Bean 定義的時候,不指定作用域的話,那么這個 Bean 對象就是單例的。

<!-- 不寫 Bean 的作用域,默認(rèn)作用域?yàn)閱卫?-->
<bean id="accountService" class="cn.god23bin.demo.service.DefaultAccountService"/>
<!-- 寫上作用域,這里是冗余的寫法,使用 scope 屬性 -->
<bean id="accountService" class="cn.god23bin.demo.service.DefaultAccountService" scope="singleton"/>

這個單例對象是存儲在一個緩存區(qū)域中的,在后續(xù)的請求或者引用中,Spring 就會返回這個緩存的對象。

實(shí)際上,Spring 中的單例的 Bean 對象是不同于 Gang of Four 設(shè)計(jì)模式中的所定義的單例模式的。

設(shè)計(jì)模式(Design Pattern)是前輩們對代碼開發(fā)經(jīng)驗(yàn)的總結(jié),是解決特定問題的一系列套路。它不是語法規(guī)定,而是一套用來提高代碼可復(fù)用性、可維護(hù)性、可讀性、穩(wěn)健性以及安全性的解決方案。

1995 年,GoF(Gang of Four,四人組/四人幫)合作出版了《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》一書,共收錄了 23 種設(shè)計(jì)模式,從此樹立了軟件設(shè)計(jì)模式領(lǐng)域的里程碑,人稱「GoF設(shè)計(jì)模式」。

設(shè)計(jì)模式中的單例模式是硬編碼的方式,以便每個 ClassLoader 只創(chuàng)建一個特定類的一個實(shí)例。

而 Spring 單例的范圍是指每個 IoC 容器的,不同 IoC 容器維護(hù)自己的 Bean 的單例對象。

2. Prototype Scope

Bean 的作用域是 prototype,中文意思是原型,實(shí)際上這里是省略了 non-singleton,這個作用域的全稱是 non-singleton prototype scope,即「非單例原型的作用域」。

顧名思義,這個作用域下的 Bean 不是單例的,意思就是說 Bean 是多例的,每一次的請求或者引用,都會創(chuàng)建一個新的 Bean 對象。

當(dāng)然這里的請求或者引用的意思是指,非單例原型的 Bean 被注入到另一個 Bean 中的時候(Bean 作為屬性被引用),或者我們直接通過容器的 getBean() 方法調(diào)用來請求它的時候,就會創(chuàng)建一個新的對象。

在 XML 中指定了這個 Bean 的作用域?yàn)?nbsp;prototype。

<bean id="accountService" class="cn.god23bin.demo.service.DefaultAccountService" scope="prototype"/>

在 prototype 作用域下的 Bean,Spring 是不會負(fù)責(zé)該 Bean 的銷毀周期中回調(diào)的方法的,如果該 Bean 擁有一些重要的資源,想在該 Bean 對象銷毀時釋放這些資源,那么需要自定義 BeanPostProcessor(Bean 的后置處理器),它持有我們需要清理的 Bean 的引用。

在某些方面來說,在 prototype 作用域下的 Bean 的作用是代替 new 操作的。

其余 4 種作用域

requestsession、application 和 websocket scope 只有在使用 Web 感知的 Spring ApplicationContext 實(shí)現(xiàn)(如 XmlWebApplicationContext)時才可用。

簡而言之,一般是在 Web 應(yīng)用下,借助 Spring 的 Web 模塊,就能使用這 4 種作用域。

如果你將這些 scope 與常規(guī)的 Spring IoC 容器(如 ClassPathXmlApplicationContext)一起使用,就會拋出一個 IllegalStateException,提示有未知的 Bean scope。

3. Request Scope

<bean id="loginController" class="cn.god23bin.demo.controller.LoginController" scope="request"/>

Spring IoC 容器為每一個 HTTP 請求使用 loginController Bean 定義來創(chuàng)建 LoginController Bean 的新實(shí)例,從而實(shí)現(xiàn)這種 request 作用域。

你可以隨心所欲地改變被創(chuàng)建的實(shí)例的內(nèi)部狀態(tài),因?yàn)閺耐粋€ loginController Bean 定義中創(chuàng)建的其他實(shí)例不會看到這些狀態(tài)的變化。它們是針對單個請求的,當(dāng)請求完成處理時,該請求所涉及的 Bean 會被丟棄。

4. Session Scope

<bean id="userPreferences" class="cn.god23bin.demo.UserPreferences" scope="session"/>

Spring IoC 容器通過使用 userPreferences Bean 定義,在單個HTTP Session 的生命周期內(nèi)創(chuàng)建一個新的 UserPreferences Bean 實(shí)例。

與 request scope 的 Bean 一樣,你可以隨心所欲地改變被創(chuàng)建的實(shí)例的內(nèi)部狀態(tài),要知道其他 HTTP Session 實(shí)例也在使用從同一個 userPreferences Bean定義中創(chuàng)建的實(shí)例,它們不會看到這些狀態(tài)的變化,因?yàn)樗鼈兪翘囟ㄓ趩蝹€HTTP Session。當(dāng)HTTP Session 最終被丟棄時,作用于該特定HTTP Session 的 Bean 也被丟棄。

5. Application Scope

<bean id="appPreferences" class="cn.god23bin.demo.AppPreferences" scope="application"/>

Spring 容器通過為整個Web應(yīng)用程序使用一次 appPreferences Bean 定義來創(chuàng)建 AppPreferences Bean的新實(shí)例。

這有點(diǎn)類似于Spring的 singleton Bean,但在兩個重要方面有所不同。

它是每個 ServletContext 的單例,而不是每個 Spring ApplicationContext(在任何給定的Web應(yīng)用程序中可能有幾個)。

6. WebSocket Scope

這里就涉及到 WebSocket 了,目前先不討論。后面再來填坑~

不同作用域的 Bean 之間的依賴關(guān)系

這里討論的,一般就是單例作用域的 Bean 和原型作用域的 Bean 之間的依賴關(guān)系。

現(xiàn)在舉個例子,假設(shè)有兩個 Java 類交給了 Spring IoC 容器管理,分別是 SingletonBean 類和 PrototypeBean 類。

其中 SingletonBean 是單例作用域的 Bean,而 PrototypeBean 是原型作用域的 Bean。

那么當(dāng):

  • SingletonBean 的依賴項(xiàng)是 PrototypeBean 時,PrototypeBean 對象只會初始化一次并注入到 SingletonBean,這樣 PrototypeBean 就起不到原型作用域的效果。
  • PrototypeBean 的依賴項(xiàng)是 SingletonBean 時,每次 PrototypeBean 對象都會創(chuàng)建,這些對象都依賴于一個單例對象,此時沒任何問題。

方法注入

Spring 提供了一種稱為方法注入(Method Injection)的機(jī)制來解決原型作用域的 Bean 在被注入到單例作用域的 Bean 中時只創(chuàng)建一個實(shí)例的問題。

方法注入允許每次調(diào)用方法時都獲取一個新的原型作用域的 Bean 實(shí)例

方法注入是通過在 SingletonBean 中定義一個返回 PrototypeBean 實(shí)例的方法來實(shí)現(xiàn)的。這樣,在每次需要使用 PrototypeBean 的地方,可以通過調(diào)用該方法獲取一個新的實(shí)例。

以下是使用方法注入解決 Prototype Bean 作用域的示例:

public abstract class SingletonBean {
    public abstract PrototypeBean getPrototypeBean();
    public void doSomething() {
        PrototypeBean prototypeBean = getPrototypeBean();
        // 使用 Prototype Bean 進(jìn)行操作
    }
}
public class PrototypeBean {
    // Prototype Bean 的定義
}

在上述示例中,SingletonBean 是一個抽象類,其中聲明了一個抽象方法 getPrototypeBean(),該方法返回一個 PrototypeBean 實(shí)例。在 doSomething() 方法中,通過調(diào)用 getPrototypeBean() 方法獲取一個新的 PrototypeBean 實(shí)例,以便在每次調(diào)用 doSomething() 時使用不同的實(shí)例。

然后,可以通過具體的子類來實(shí)現(xiàn) SingletonBean,并實(shí)現(xiàn) getPrototypeBean() 方法以返回相應(yīng)的 PrototypeBean 實(shí)例。

通過方法注入,每次調(diào)用 doSomething() 方法時都會獲取一個新的 PrototypeBean 實(shí)例,從而解決了在 Singleton Bean 中注入 Prototype Bean 時只創(chuàng)建一個實(shí)例的問題。

需要注意的是,方法注入需要在配置文件或使用注解時進(jìn)行特殊的配置,具體的配置方式基本如下。

1. XML 配置方式

當(dāng)然,上面舉例是一個抽象類,不是抽象類也是可以的,比如:

public class SingletonBean {
    // 方法注入,Spring 會幫我們返回這個對象,這里寫成 null 即可
    public PrototypeBean getPrototypeBean() {
        return null;
    }
    public void doSomething() {
        PrototypeBean prototypeBean = getPrototypeBean();
        // 使用 Prototype Bean 進(jìn)行操作
    }
}
public class PrototypeBean {
    // Prototype Bean 的定義
}

接著,單獨(dú)上面是沒有實(shí)現(xiàn)不了方法注入的,還需要結(jié)合配置元數(shù)據(jù),現(xiàn)在在 XML 配置文件中使用 <lookup-method /> 標(biāo)簽來實(shí)現(xiàn)方法注入。

<bean id="singletonBean" class="cn.god23bin.demo.domain.model.SingletonBean">
    <lookup-method name="getPrototypeBean" bean="prototypeBean"/>
</bean>
<bean id="prototypeBean" class="cn.god23bin.demo.domain.model.PrototypeBean" scope="prototype"/>

上面的配置示例中,singletonBean 是一個單例 Bean,通過 <lookup-method /> 標(biāo)簽指定了一個名為 getPrototypeBean 的方法,并引用了一個原型 Bean prototypeBean。

在運(yùn)行時,每次調(diào)用 getPrototypeBean 方法時,都會返回一個新的 prototypeBean 實(shí)例。

2. 注解配置方式

使用 @Lookup 注解來實(shí)現(xiàn)方法注入。

@Component
public class SingletonBean {
    private PrototypeBean prototypeBean;
    @Lookup
    public PrototypeBean getPrototypeBean() {
        return null; // 實(shí)際上會由 Spring 生成具體實(shí)現(xiàn)
    }
    // 其他代碼...
}
@Component
@Scope("prototype")
public class PrototypeBean {
    // 具體的原型 Bean 實(shí)現(xiàn)
}

在上面的示例中,SingletonBean 使用了 @Lookup 注解標(biāo)記了一個名為 getPrototypeBean 的方法。在運(yùn)行時,Spring 會為這個方法生成具體的實(shí)現(xiàn),以實(shí)現(xiàn)方法注入。

總結(jié)

簡單總結(jié)下:

Bean 的作用域在 Bean 定義的時候可以進(jìn)行指定,默認(rèn)是單例的,多例的 Bean 就是所謂的原型作用域。

一共 6 種作用域需要熟悉,其中 4 種是在具有 Web 感知能力的 Spring IoC (應(yīng)用上下文)下才有的作用域。

對于單例 Bean 依賴原型 Bean 的問題,可以通過方法注入解決,兩種寫法實(shí)現(xiàn)方法注入,一種是 XML,另一種是注解的方式。

本文詳細(xì)介紹了Spring框架中的Bean作用域(Scope)的使用。首先,介紹了Singleton作用域,它是默認(rèn)的作用域,每個Spring容器中只有一個實(shí)例。然后,討論了Prototype作用域,它在每次請求時創(chuàng)建一個新的實(shí)例。接下來,解釋了Request作用域,它在每個HTTP請求中創(chuàng)建一個實(shí)例。然后,介紹了Session作用域,它在每個用戶會話中創(chuàng)建一個實(shí)例。最后,討論了Application作用域,它在整個應(yīng)用程序中創(chuàng)建一個實(shí)例。對于每種作用域,文章解釋了其特點(diǎn)、適用場景和配置方式。通過理解和正確使用Spring框架中的Bean作用域,開發(fā)人員可以更好地管理和控制Bean對象的生命周期和可見性,提高應(yīng)用程序的性能和可維護(hù)性。

到此這篇關(guān)于 Spring 框架中的 Bean 作用域(Scope)使用詳解的文章就介紹到這了,更多相關(guān)Spring Bean 的作用域內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java 按照字節(jié)來截取字符串的代碼(不會出現(xiàn)半個漢字)

    Java 按照字節(jié)來截取字符串的代碼(不會出現(xiàn)半個漢字)

    Java 按照字節(jié)來截取字符串的工具,不會出現(xiàn)半個漢字。一個中文兩個字節(jié),一個英文字符只占 1 個字節(jié)** 1. 通常我們用于前端顯示的時候,防止標(biāo)題過長
    2014-01-01
  • IntelliJ?IDEA安裝與基礎(chǔ)配置指南

    IntelliJ?IDEA安裝與基礎(chǔ)配置指南

    IntelliJ?IDEA是一款由JetBrains公司開發(fā)的Java集成開發(fā)環(huán)境,支持Java、Kotlin、Groovy、Scala等多種編程語言,IntelliJ?IDEA作為一款強(qiáng)大的開發(fā)工具,被廣泛應(yīng)用于Java開發(fā)、Web開發(fā)、Android開發(fā)等領(lǐng)域,本文給大家介紹了IntelliJ?IDEA安裝與基礎(chǔ)配置
    2025-07-07
  • 自定義注解SpringBoot防重復(fù)提交AOP方法詳解

    自定義注解SpringBoot防重復(fù)提交AOP方法詳解

    該文章描述了一個防止重復(fù)提交的流程,通過HttpServletRequest對象獲取請求信息,生成唯一標(biāo)識,使用Redis分布式鎖判斷請求是否重復(fù)提交,并通過自定義注解和切面實(shí)現(xiàn)
    2025-12-12
  • 使用Easyexcel實(shí)現(xiàn)不同場景的數(shù)據(jù)導(dǎo)出功能

    使用Easyexcel實(shí)現(xiàn)不同場景的數(shù)據(jù)導(dǎo)出功能

    這篇文章主要為大家詳細(xì)介紹了如何在不同場景下使用Easyexcel實(shí)現(xiàn)數(shù)據(jù)導(dǎo)出功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-03-03
  • 使用log4j MDC實(shí)現(xiàn)日志追蹤

    使用log4j MDC實(shí)現(xiàn)日志追蹤

    這篇文章主要介紹了使用log4j MDC實(shí)現(xiàn)日志追蹤方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • springboot多環(huán)境(dev、test、prod)配置詳解

    springboot多環(huán)境(dev、test、prod)配置詳解

    這篇文章主要介紹了springboot多環(huán)境(dev、test、prod)配置詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-04-04
  • java calendar 日期實(shí)現(xiàn)不斷加一天的代碼

    java calendar 日期實(shí)現(xiàn)不斷加一天的代碼

    這篇文章主要介紹了java calendar 日期實(shí)現(xiàn)不斷加一天的代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Java詳解IO流創(chuàng)建讀取與寫入操作

    Java詳解IO流創(chuàng)建讀取與寫入操作

    這篇文章主要介紹了Java IO流,同時也介紹了流中的一些相關(guān)的內(nèi)容,并且通過大量的案例供大家理解。最后通過一些經(jīng)典的案例幫助大家對前面所學(xué)的知識做了一個綜合的應(yīng)用,需要的朋友可以參考一下
    2022-05-05
  • Spring @CrossOrigin 注解原理實(shí)現(xiàn)

    Spring @CrossOrigin 注解原理實(shí)現(xiàn)

    這篇文章主要介紹了Spring @CrossOrigin 注解原理實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 解決spring-boot2.0.6中webflux無法獲得請求IP的問題

    解決spring-boot2.0.6中webflux無法獲得請求IP的問題

    這幾天在用 spring-boot 2 的 webflux 重構(gòu)一個工程,寫到了一個需要獲得客戶端請求 IP 的地方,在寫的過程中遇到很多問題,下面小編通過一段代碼給大家介紹解決spring-boot2.0.6中webflux無法獲得請求IP的問題,感興趣的朋友跟隨小編一起看看吧
    2018-10-10

最新評論

娱乐| 渭南市| 巩义市| 嘉祥县| 岐山县| 灌阳县| 泰安市| 屏东县| 张家港市| 大同县| 布拖县| 霸州市| 平武县| 关岭| 蒙山县| 漯河市| 南京市| 台北县| 天峻县| 环江| 保靖县| 云阳县| 江安县| 武隆县| 大姚县| 塔城市| 黄山市| 遂昌县| 九台市| 石首市| 卫辉市| 临沂市| 内丘县| 黄浦区| 栾城县| 娄底市| 长春市| 潮州市| 民和| 岳池县| 双辽市|