一、前言
創(chuàng)建 BeanDefinition 時(shí),就等于創(chuàng)建了一個(gè)配方,用于創(chuàng)建由 BeanDefinition 所定義的類實(shí)例。BeanDefinition 是配方的這種思想很重要,因?yàn)檫@意味著,與使用類一樣,也可通過(guò)一個(gè)配方創(chuàng)建多個(gè)對(duì)象實(shí)例。
有如下優(yōu)點(diǎn):
- 可以控制要插入到從特定 BeanDefinition 創(chuàng)建的對(duì)象中的各種依賴項(xiàng)和配置值
- 可以控制從特定 BeanDefinition 創(chuàng)建的對(duì)象的作用域。
這種方式功能強(qiáng)大且靈活,因?yàn)殚_(kāi)發(fā)者可以選擇通過(guò)配置創(chuàng)建的對(duì)象的作用域,而不必在Java類級(jí)別上考慮對(duì)象的范圍。
當(dāng)然了,作為靈活的框架,Spring 還允許開(kāi)發(fā)者創(chuàng)建自定義的作用域。
1.1 詳細(xì)介紹下 singleton 作用域?
僅管理一個(gè)singleton bean的一個(gè)共享實(shí)例,并且所有對(duì)具有ID或與該 BeanDefinition 相匹配的ID的bean的請(qǐng)求都將導(dǎo)致該特定的bean實(shí)例由Spring容器返回。
換言之,當(dāng)我們定義了一個(gè) BeanDefinition 并且其作用域?yàn)?singleton 時(shí),IoC容器將為該 BeanDefinition 所定義的對(duì)象創(chuàng)建一個(gè)實(shí)例。該單實(shí)例存儲(chǔ)在此類單例bean的緩存中,并且對(duì)該命名bean的所有后續(xù)請(qǐng)求和引用都返回該緩存的對(duì)象。
1.2 和單例模式有何聯(lián)系去區(qū)別呢?
Spring的 singleton bean概念與傳說(shuō)中的四人幫創(chuàng)建的《Gang of Four (GoF) patterns》一書中定義的單例模式并不一樣。
- GoF的單例模式會(huì)硬編碼對(duì)象的作用域,使得每個(gè)類加載器只能創(chuàng)建一個(gè)特定類的唯一實(shí)例
- 因此,最恰當(dāng)?shù)膽?yīng)該將Spring單例的作用域描述為一個(gè)容器對(duì)應(yīng)一個(gè)bean。若我們?cè)趩蝹€(gè)Spring容器中為特定類定義一個(gè)bean,則Spring容器將創(chuàng)建該 BeanDefinition 所定義的類的一個(gè)且只有一個(gè)實(shí)例。
單例作用域是Spring中的默認(rèn)作用域。要將bean定義為XML中的單例,可以定義bean,如以下示例所示:
1.3 Prototype作用域
Bean部署的非單一原型作用域會(huì)在每次請(qǐng)求特定bean時(shí)創(chuàng)建一個(gè)新bean實(shí)例。也就是說(shuō),該Bean被注入到另一個(gè)Bean中,或者您可以通過(guò)容器上的getBean()方法調(diào)用來(lái)請(qǐng)求它。通常,應(yīng)將原型作用域用于所有有狀態(tài)Bean,將單例作用域用于無(wú)狀態(tài)Bean。
在 Spring 中,那些組成應(yīng)用程序的主體及由 Spring IOC 容器所管理的對(duì)象,被稱之為 bean。
簡(jiǎn)單地講,bean 就是由 IOC 容器初始化、裝配及管理的對(duì)象,除此之外,bean 就與應(yīng)用程序中的其他對(duì)象沒(méi)有什么區(qū)別了。
而 bean 的定義以及 bean 相互間的依賴關(guān)系將通過(guò)配置元數(shù)據(jù)來(lái)描述。
Spring中的bean默認(rèn)都是單例的,這些單例Bean在多線程程序下如何保證線程安全呢?
例如對(duì)于Web應(yīng)用來(lái)說(shuō),Web容器對(duì)于每個(gè)用戶請(qǐng)求都創(chuàng)建一個(gè)單獨(dú)的Sevlet線程來(lái)處理請(qǐng)求,引入Spring框架之后,每個(gè)Action都是單例的,那么對(duì)于Spring托管的單例Service Bean,如何保證其安全呢?
Spring的單例是基于BeanFactory也就是Spring容器的,單例Bean在此容器內(nèi)只有一個(gè)Java的單例是基于 JVM,每個(gè) JVM 內(nèi)只有一個(gè)實(shí)例
二、bean的作用域
創(chuàng)建一個(gè)bean定義,其實(shí)質(zhì)是用該bean定義對(duì)應(yīng)的類來(lái)創(chuàng)建真正實(shí)例的“配方”。
把bean定義看成一個(gè)配方很有意義,它與class很類似,只根據(jù)一張“處方”就可以創(chuàng)建多個(gè)實(shí)例。
不僅可以控制注入到對(duì)象中的各種依賴和配置值,還可以控制該對(duì)象的作用域。
這樣可以靈活選擇所建對(duì)象的作用域,而不必在Java Class級(jí)定義作用域。
Spring Framework支持五種作用域,分別闡述如下表。
五種作用域中,request、session 和 global session 三種作用域僅在基于web的應(yīng)用中使用(不必關(guān)心你所采用的是什么web應(yīng)用框架),只能用在基于 web 的 Spring ApplicationContext 環(huán)境。
三、singleton —— 唯一 bean 實(shí)例
當(dāng)一個(gè) bean 的作用域?yàn)?singleton,那么Spring IoC容器中只會(huì)存在一個(gè)共享的 bean 實(shí)例,并且所有對(duì) bean 的請(qǐng)求,只要 id 與該 bean 定義相匹配,則只會(huì)返回bean的同一實(shí)例。
singleton 是單例類型(對(duì)應(yīng)于單例模式),就是在創(chuàng)建起容器時(shí)就同時(shí)自動(dòng)創(chuàng)建了一個(gè)bean的對(duì)象,不管你是否使用,但我們可以指定Bean節(jié)點(diǎn)的 lazy-init=”true”
來(lái)延遲初始化bean,這時(shí)候,只有在第一次獲取bean時(shí)才會(huì)初始化bean,即第一次請(qǐng)求該bean時(shí)才初始化。
每次獲取到的對(duì)象都是同一個(gè)對(duì)象。注意,singleton 作用域是Spring中的缺省作用域。要在XML中將 bean 定義成 singleton ,可以這樣配置:
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">
也可以通過(guò) @Scope
注解(它可以顯示指定bean的作用范圍。)的方式
@Service
@Scope("singleton")
public class ServiceImpl{
}
四、prototype——每次請(qǐng)求都會(huì)創(chuàng)建一個(gè)新的 bean 實(shí)例
當(dāng)一個(gè)bean的作用域?yàn)?prototype,表示一個(gè) bean 定義對(duì)應(yīng)多個(gè)對(duì)象實(shí)例。
prototype 作用域的 bean 會(huì)導(dǎo)致在每次對(duì)該 bean 請(qǐng)求(將其注入到另一個(gè) bean 中,或者以程序的方式調(diào)用容器的 getBean() 方法)時(shí)都會(huì)創(chuàng)建一個(gè)新的 bean 實(shí)例。prototype 是原型類型,它在我們創(chuàng)建容器的時(shí)候并沒(méi)有實(shí)例化,而是當(dāng)我們獲取bean的時(shí)候才會(huì)去創(chuàng)建一個(gè)對(duì)象,而且我們每次獲取到的對(duì)象都不是同一個(gè)對(duì)象。
對(duì)有狀態(tài)的 bean 應(yīng)該使用 prototype 作用域,而對(duì)無(wú)狀態(tài)的 bean 則應(yīng)該使用 singleton 作用域。
在 XML 中將 bean 定義成 prototype
<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>
或者
<bean id="account" class="com.foo.DefaultAccount" singleton="false"/>
通過(guò) @Scope
注解的方式實(shí)現(xiàn)就不做演示了。
五、request——每一次HTTP請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的bean
該bean僅在當(dāng)前HTTP request內(nèi)有效
request只適用于Web程序,每一次 HTTP 請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的bean,同時(shí)該bean僅在當(dāng)前HTTP request內(nèi)有效,當(dāng)請(qǐng)求結(jié)束后,該對(duì)象的生命周期即告結(jié)束。
在 XML 中將 bean 定義成 request ,可以這樣配置:
<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>
六、session——每一次HTTP請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的 bean
該bean僅在當(dāng)前 HTTP session 內(nèi)有效。
session只適用于Web程序,session 作用域表示該針對(duì)每一次 HTTP 請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的 bean,同時(shí)該 bean 僅在當(dāng)前 HTTP session 內(nèi)有效.與request作用域一樣,可以根據(jù)需要放心的更改所創(chuàng)建實(shí)例的內(nèi)部狀態(tài),而別的 HTTP session 中根據(jù) userPreferences 創(chuàng)建的實(shí)例,將不會(huì)看到這些特定于某個(gè) HTTP session 的狀態(tài)變化。當(dāng)HTTP session最終被廢棄的時(shí)候,在該HTTP session作用域內(nèi)的bean也會(huì)被廢棄掉。
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
七、globalSession
global session 作用域類似于標(biāo)準(zhǔn)的 HTTP session 作用域,不過(guò)僅僅在基于 portlet 的 web 應(yīng)用中才有意義。Portlet 規(guī)范定義了全局 Session 的概念,它被所有構(gòu)成某個(gè) portlet web 應(yīng)用的各種不同的 portle t所共享。在global session 作用域中定義的 bean 被限定于全局portlet Session的生命周期范圍內(nèi)。
<bean id="user" class="com.foo.Preferences "scope="globalSession"/>
Spring框架支持5種作用域,有三種作用域是當(dāng)開(kāi)發(fā)者使用基于web的ApplicationContext
的時(shí)候才生效的
下面就是Spring內(nèi)置支持的作用域
作用域 | 描述 |
單例(singleton) | (默認(rèn))每一個(gè)Spring IoC容器都擁有唯一的一個(gè)實(shí)例對(duì)象 |
原型(prototype) | 一個(gè)Bean定義可以創(chuàng)建任意多個(gè)實(shí)例對(duì)象 |
請(qǐng)求(request) | 一個(gè)HTTP請(qǐng)求會(huì)產(chǎn)生一個(gè)Bean對(duì)象,也就是說(shuō),每一個(gè)HTTP請(qǐng)求都有自己的Bean實(shí)例。只在基于web的Spring ApplicationContext 中可用 |
會(huì)話(session) | 限定一個(gè)Bean的作用域?yàn)镠TTPsession 的生命周期。同樣,只有基于web的Spring ApplicationContext 才能使用 |
全局會(huì)話(global session) | 限定一個(gè)Bean的作用域?yàn)槿諬TTPSession 的生命周期。通常用于門戶網(wǎng)站場(chǎng)景,同樣,只有基于web的Spring ApplicationContext 可用 |
應(yīng)用(application) | 限定一個(gè)Bean的作用域?yàn)?code>ServletContext的生命周期。同樣,只有基于web的Spring ApplicationContext 可用 |
在Spring 3.0中,線程作用域是可用的,但不是默認(rèn)注冊(cè)的
7.1 singleton
全局只有一個(gè)共享的實(shí)例,所有將單例Bean作為依賴的情況下,容器返回將是同一個(gè)實(shí)例
換言之,當(dāng)開(kāi)發(fā)者定義一個(gè)Bean的作用域?yàn)閱卫龝r(shí),Spring IoC容器只會(huì)根據(jù)Bean定義來(lái)創(chuàng)建該Bean的唯一實(shí)例。這些唯一的實(shí)例會(huì)緩存到容器中,后續(xù)針對(duì)單例Bean的請(qǐng)求和引用,都會(huì)從這個(gè)緩存中拿到這個(gè)唯一的實(shí)例
7.2 單例Bean和單例模式
- 單例模式是將一個(gè)對(duì)象的作用域硬編碼,一個(gè)ClassLoader只有唯一的一個(gè)實(shí)例
- 而Spring的單例作用域,是
基于每個(gè)容器
,每個(gè)Bean只有一個(gè)實(shí)例
這意味著,如果開(kāi)發(fā)者根據(jù)一個(gè)類定義了一個(gè)Bean在單個(gè)的Spring容器中,那么Spring容器會(huì)根據(jù)Bean定義創(chuàng)建一個(gè)唯一的Bean實(shí)例。默認(rèn)情況下,它們?yōu)槊總€(gè)給定的org.springframework.context.ApplicationContext實(shí)例存在唯一的一個(gè)bean (有點(diǎn)別扭,也就是可以有多個(gè)Spring容器,每一個(gè)容器內(nèi)存在唯一bean實(shí)例).這意味著如果你有兩個(gè)或更多上下文,所有這些上下文都由同一Java的類加載器管理(因?yàn)樵谕粋€(gè)jvm環(huán)境中),則可能會(huì)有多個(gè)給定bean的實(shí)例。唯一需要做到的是必須在每個(gè)上下文中定義此bean.
所以你可以看到,bean只是一個(gè)上下文的單例
你不應(yīng)該將Spring的單例概念與設(shè)計(jì)模式中的的單例混淆
單例作用域是Spring的默認(rèn)作用域,下面的例子是在基于XML的配置中配置單例模式的Bean。
<bean id="accountService" class="com.sss.DefaultAccountService"/>
<!-- the following is equivalent, though redundant (singleton scope is the default) -->
<bean id="accountService" class="com.sss.DefaultAccountService" scope="singleton"/>
八、prototype
每次請(qǐng)求Bean實(shí)例時(shí),返回的都是新實(shí)例的Bean對(duì)象
也就是說(shuō),每次注入到另外的Bean或者通過(guò)調(diào)用getBean()
來(lái)獲得的Bean都將是全新的實(shí)例。
這是基于線程安全性:
- 有狀態(tài)的Bean對(duì)象用prototype作用域
- 無(wú)狀態(tài)的Bean對(duì)象用singleton 作用域
下面的例子說(shuō)明了Spring的原型作用域。DAO通常不會(huì)配置為原型對(duì)象,因?yàn)榈湫偷腄AO是不會(huì)有任何的狀態(tài)的。
下面的例子展示了XML中如何定義一個(gè)原型的Bean:
<bean id="accountService"
class="com.javaedge.DefaultAccountService" scope="prototype"/>
與其他的作用域相比,Spring不會(huì)完全管理原型Bean的生命周期:
Spring容器只會(huì)初始化配置以及裝載這些Bean,傳遞給Client。
但是之后就不會(huì)再去管原型Bean之后的動(dòng)作了。
也就是說(shuō),初始化生命周期回調(diào)方法在所有作用域的Bean是都會(huì)調(diào)用的,但是銷毀生命周期回調(diào)方法在原型Bean是不會(huì)調(diào)用的
所以,客戶端代碼必須注意清理原型Bean以及釋放原型Bean所持有的一些資源。
可以通過(guò)使用自定義的bean post-processor
來(lái)讓Spring釋放掉原型Bean所持有的資源。
在某些方面來(lái)說(shuō),Spring容器的角色就是取代了Java的new
操作符,所有的生命周期的控制需要由客戶端來(lái)處理。
Singleton beans with prototype-bean dependencies 在原型bean中放置單例
如果注入的單例對(duì)象真的是一個(gè)單例的bean(沒(méi)有狀態(tài)),這個(gè)真的沒(méi)一點(diǎn)問(wèn)題
想象一下,對(duì)于我們的購(gòu)物車,我們需要注入產(chǎn)品服務(wù)。此服務(wù)只會(huì)檢查添加到購(gòu)物車的產(chǎn)品是否庫(kù)存。由于服務(wù)沒(méi)有狀態(tài),并且會(huì)基于在方法簽名中所傳遞的對(duì)象進(jìn)行驗(yàn)證,因此不存在風(fēng)險(xiǎn)
當(dāng)使用單例Bean的時(shí)候,而該單例Bean的依賴是原型Bean時(shí),需要注意的是依賴的解析都是在初始化的階段
因此,如果將原型Bean注入到單例的Bean之中,只會(huì)請(qǐng)求一次原型Bean,然后注入到單例Bean中。這個(gè)依賴的原型Bean仍然屬于只有一個(gè)實(shí)例的。
然而,假設(shè)你需要單例Bean對(duì)原型的Bean的依賴
需要每次在運(yùn)行時(shí)都請(qǐng)求一個(gè)新的實(shí)例,那么你就不能夠?qū)⒁粋€(gè)原型的Bean來(lái)注入到一個(gè)單例的Bean當(dāng)中了,因?yàn)橐蕾囎⑷胫粫?huì)進(jìn)行一次
當(dāng)Spring容器在實(shí)例化單例Bean的時(shí)候,就會(huì)解析以及注入它所需的依賴
如果實(shí)在需要每次都請(qǐng)求一個(gè)新的實(shí)例,可以通過(guò)bean工廠手動(dòng)獲取實(shí)例,也可以參考Dependencies中的方法注入部分。
##使用單例還是原型?
Singleton適用于無(wú)狀態(tài)的bean,比如一個(gè)service,DAO或者controller
他們都沒(méi)有自己的狀態(tài)(舉個(gè)簡(jiǎn)單的例子,一個(gè)函數(shù)sin(x),這個(gè)函數(shù)本身就是無(wú)狀態(tài)的,所以我們現(xiàn)在喜歡的函數(shù)式編程也遵循這個(gè)理念)。而是根據(jù)傳輸?shù)膮?shù)執(zhí)行一些操作(作為HTTP請(qǐng)求參數(shù))。
另一方面,我們可以通過(guò)狀態(tài)bean管理一些狀態(tài)。比如購(gòu)物車bean,假如它是一個(gè)單例,那么兩個(gè)不同消費(fèi)者購(gòu)買的產(chǎn)品將被放置在同一個(gè)對(duì)象上。而如果其中一個(gè)消費(fèi)者想要?jiǎng)h除一個(gè)產(chǎn)品,另一個(gè)消費(fèi)者就鐵定不高興。這也就是狀態(tài)類對(duì)象應(yīng)該是原型
#3. Request
Spring容器會(huì)在每次用到loginAction
來(lái)處理每個(gè)HTTP請(qǐng)求的時(shí)候都會(huì)創(chuàng)建一個(gè)新的LoginAction
實(shí)例。也就是說(shuō),loginAction
Bean的作用域是HTTPRequest
級(jí)別的。 開(kāi)發(fā)者可以隨意改變實(shí)例的狀態(tài),因?yàn)槠渌ㄟ^(guò)loginAction
請(qǐng)求來(lái)創(chuàng)建的實(shí)例根本看不到開(kāi)發(fā)者改變的實(shí)例狀態(tài),所有創(chuàng)建的Bean實(shí)例都是根據(jù)獨(dú)立的請(qǐng)求來(lái)的。當(dāng)請(qǐng)求處理完畢,這個(gè)Bean也會(huì)銷毀。
每個(gè)請(qǐng)求初始化具有此作用域的Bean注解。這聽(tīng)起來(lái)像是原型作用域的描述,但它們有一些差異。
- 原型作用域在Spring的上下文中可用。而請(qǐng)求作用域僅適用于Web應(yīng)用程序
- 原型bean根據(jù)需求進(jìn)行初始化,而請(qǐng)求bean是在每個(gè)請(qǐng)求下構(gòu)建的
需要說(shuō)的是,request作用域bean在其作用域內(nèi)有且僅有一個(gè)實(shí)例。而你可以擁有一個(gè)或多個(gè)原型作用域bean實(shí)例
在以下代碼中,你可以看到請(qǐng)求作用域bean的示例:
<bean id="shoppingCartRequest" class="com.sss.scope.ShoppingCartRequest" scope="request">
<aop:scoped-proxy/>
</bean>
當(dāng)使用注解驅(qū)動(dòng)組件或Java Config時(shí),@RequestScope注解可以用于將一個(gè)組件分配給request作用域。
@RequestScope
@Component
public class ShoppingCartRequest {
// ...
}
// request bean
// injection sample
@Controller
public class TestController {
@Autowired
private ShoppingCartRequest shoppingCartRequest;
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test(HttpServletRequest request) {
LOGGER.debug("shoppingCartRequest is :"+shoppingCartRequest);
// ...
}
}
請(qǐng)注意定義內(nèi)存在的<aop: scoped-proxy />標(biāo)簽。這代表著使用代理對(duì)象。所以實(shí)際上,TestController持有的是代理對(duì)象的引用。我們所有的調(diào)用該對(duì)象都會(huì)轉(zhuǎn)發(fā)到真正的ShoppingCartRequest對(duì)象。
有時(shí)我們需要使用DispatcherServlet的另一個(gè)servlet來(lái)處理請(qǐng)求。在這種情況下,我們必須確保Spring中所有請(qǐng)求都可用(否則可以拋出與下面類似的異常)。為此,我們需要在web.xml中定義一個(gè)監(jiān)聽(tīng)器:
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
調(diào)用/測(cè)試URL后,你應(yīng)該能在日志中的發(fā)現(xiàn)以下信息:
shoppingCartRequest is :com.migo.scope.ShoppingCartRequest@2586b11c shoppingCartRequest is :com.migo.scope.ShoppingCartRequest@3bd5b945
如果我們嘗試在單例bean中使用request作用域的bean,則會(huì)在應(yīng)用程序上下文加載階段拋出一個(gè)BeanCreationException
#4. session
參考如下的Bean定義:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
Spring容器會(huì)在每次調(diào)用到userPreferences
在一個(gè)單獨(dú)的HTTP會(huì)話周期來(lái)創(chuàng)建一個(gè)新的UserPreferences
實(shí)例。換言之,userPreferences
Bean的作用域是HTTPSession
級(jí)別的。 在request-scoped
作用域的Bean上,開(kāi)發(fā)者可以隨意的更改實(shí)例的狀態(tài),同樣,其他的HTTPSession
基本的實(shí)例在每個(gè)Session都會(huì)請(qǐng)求userPreferences
來(lái)創(chuàng)建新的實(shí)例,所以開(kāi)發(fā)者更改Bean的狀態(tài),對(duì)于其他的Bean仍然是不可見(jiàn)的。當(dāng)HTTPSession
銷毀了,那么根據(jù)這個(gè)Session
來(lái)創(chuàng)建的Bean也就銷毀了。
Session作用域的bean與request 作用域的bean沒(méi)有太大不同。它們也與純Web應(yīng)用程序上下文相關(guān)聯(lián)。注解為Session作用域的Bean對(duì)于每個(gè)用戶的會(huì)話僅創(chuàng)建一次。他們?cè)跁?huì)話結(jié)束時(shí)被破壞銷毀掉。
由Session作用域限制的Bean可以被認(rèn)為是面向Web的單例,因?yàn)榻o定環(huán)境(用戶會(huì)話)僅存在一個(gè)實(shí)例。但請(qǐng)記住,你無(wú)法在Web應(yīng)用程序上下文中使用它們(說(shuō)個(gè)好理解點(diǎn)的,就是一個(gè)函數(shù)內(nèi)部自定義變量所在的作用域,函數(shù)執(zhí)行完就銷毀了,沒(méi)有什么逃逸)。
想知道Session作用域bean在Spring中的操作,我們需要在配置文件中定義一個(gè)bean:
<bean id="shoppingCartRequest" class="com.migo.scope.ShoppingCartSession" scope="session">
<aop:scoped-proxy/>
</bean>
通過(guò)@Autowired
注解,查找這個(gè)bean的方式與request 作用域的bean相同??梢钥吹揭韵陆Y(jié)果:
你可以看到,前5個(gè)打印輸出代表相同的對(duì)象。最后一個(gè)是不同的。這是什么意思 ?簡(jiǎn)單來(lái)說(shuō),這代表 著一個(gè)新的用戶使用自動(dòng)注入的Session作用域訪問(wèn)該頁(yè)面。我們可以通過(guò)打開(kāi)兩個(gè)瀏覽器的測(cè)試頁(yè)(/test)來(lái)觀察它。每個(gè)都將初始化一個(gè)新的會(huì)話Session,因此也就創(chuàng)建新的ShoppingCartSession bean
實(shí)例。
#5. global session
該部分主要是描述
portlet
的,詳情可以Google更多關(guān)于portlet
的相關(guān)信息。
參考如下的Bean定義:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/>
global session
作用域比較類似之前提到的標(biāo)準(zhǔn)的HTTPSession
,這種作用域是只應(yīng)用于基于門戶(portlet-based)的web應(yīng)用的上下之中的。門戶的Spec中定義的global session
的意義:global session
被所有構(gòu)成門戶的web應(yīng)用所共享。定義為global session
作用域的Bean是作用在全局門戶Session
的聲明周期的。
如果在使用標(biāo)準(zhǔn)的基于Servlet的Web應(yīng)用,而且定義了global session
作用域的Bean,那么只是會(huì)使用標(biāo)準(zhǔn)的HTTPSession
作用域,不會(huì)報(bào)錯(cuò)。
關(guān)于全局會(huì)話作用域(Global session scope)屬于4.3x的范疇了,Spring5已經(jīng)沒(méi)有了,Spring5文檔是去掉了因?yàn)?的存在所以還是說(shuō)兩句,它保留給portlet應(yīng)用程序。 是不是一臉懵逼,so,來(lái)解釋一下portlet是什么。Portlet是能夠生成語(yǔ)義代碼(例如:HTML)片段的小型Java Web插件。它們基于portlet容器,可以像servlet一樣處理HTTP請(qǐng)求。但是,與servlet不同,每個(gè)portlet都有不同的會(huì)話。在這種情況下,Spring提供了一個(gè)名為global-session
的作用域。通過(guò)它,一個(gè)bean可以通過(guò)應(yīng)用程序中的多個(gè)portlet共享。
至此,我們解釋了請(qǐng)求和面向會(huì)話的作用域。第一個(gè)的作用是在每個(gè)request請(qǐng)求上創(chuàng)建新的bean。第二個(gè)在Session會(huì)話開(kāi)始的時(shí)候初始化bean。
到此這篇關(guān)于超詳細(xì)相關(guān)SpringBean的作用域管理內(nèi)容總結(jié)的文章就介紹到這了,更多相關(guān)SpringBean的作用域管理的內(nèi)容請(qǐng)搜索W3Cschool以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,也希望大家以后多多支持我們!