多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php框架 > 框架設(shè)計(jì) > spring之bean的Scope

spring之bean的Scope

來源:程序員人生   發(fā)布時(shí)間:2015-04-09 09:16:30 閱讀次數(shù):3653次

上篇文章較為詳細(xì)了對(duì)各種情況下bean依賴的配置做了說明,但1直沒有對(duì)Scope這個(gè)屬性進(jìn)行說明。本篇將1起學(xué)習(xí)。本文演示代碼下載地址

當(dāng)我們?cè)趚ml配置文件中配置1個(gè)bean的定義的時(shí)候,可以認(rèn)為是配置了1個(gè)模板,可以根據(jù)這個(gè)模板來生成很多個(gè)對(duì)象來滿足全部利用程序的依賴關(guān)系,同時(shí)我們也能夠配置對(duì)象的Scope。

Scope可以理解為SpringIOC容器中的對(duì)象應(yīng)當(dāng)處的限定場(chǎng)景或說該對(duì)象的存活空間,即在IOC容器在對(duì)象進(jìn)入相應(yīng)的scope之前,生成并裝配這些對(duì)象,在該對(duì)象不再處于這些scope的限定以后,容器通常會(huì)燒毀這些對(duì)象。

截止到目前為止,spring提供了6種類型的scope:

1.               singleton 表示在spring容器中的單例,通過spring容器取得該bean時(shí)總是返回唯1的實(shí)例

2.               prototype 表示每次取得bean都會(huì)生成1個(gè)新的對(duì)象

3.               request 表示在1次http要求內(nèi)有效(只適用于web利用)

4.               session 表示在1個(gè)用戶會(huì)話內(nèi)有效(只適用于web利用)

5.               global Session 與上面類似,但是用于移動(dòng)裝備中的服務(wù)器中。

6.               globalSession 表示在全局會(huì)話內(nèi)有效(只適用于web利用)

1般情況下,前兩種的scope就已足夠滿足需求,后幾種應(yīng)用于web容器中,默許的scope是singleton。

注:spring3.0開始提供 SimpleThreadScope ,但是默許沒有注冊(cè)。

單例

基本

Singleton 是spring容器默許采取的scope。注意這里的Singleton和設(shè)計(jì)模式中所描寫的概念不同。設(shè)計(jì)模式中指每一個(gè)classLoader1個(gè)類只有1個(gè)實(shí)例,而這里指每一個(gè)Spring容器對(duì)1個(gè) beandefinition只有1個(gè)實(shí)例。

見下圖說明:


下節(jié)中的代碼集中說明Singleton和prototype 

懶加載

默許情況下,Singleton的bean是在spring容器初始化的進(jìn)程中進(jìn)行初始化的,這樣做的好處是可以盡早的發(fā)現(xiàn)配置的毛病。

但是如果有需要的話,可以取消這個(gè)機(jī)制,使用bean標(biāo)簽的lazy-init 屬性 ,以下:


<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/>

也能夠在配置文件根標(biāo)簽beans 使用以下配置,取消預(yù)加載的行動(dòng):

<beans default-lazy-init="true"> <!-- no beans will be pre-instantiated... --> </beans>

原型

Scope為prototype bean定義,每次需要的時(shí)候總是重新創(chuàng)建1個(gè)全新的對(duì)象,不論是依賴注入的需要,還是調(diào)用applicationContext的getBean方法。以下圖說明:


與其他類型的scope相比,spring不完全管理scope為prototype的生命周期,spring容器僅僅是實(shí)例化、配置和組裝1個(gè)實(shí)例給客戶,而沒有進(jìn)1步記錄它的狀態(tài)。Spring容器會(huì)履行所有bean的初始化方法,但是對(duì)scope為prototype的bean來講,其destruction生命周期函數(shù)不會(huì)被履行,所以其持有的昂貴的資源需要客戶端自己釋放。

下面的代碼進(jìn)1步理解,首先是Client1和client2 兩個(gè)類,他們完全1樣,而AccoutDao是1個(gè)空類,甚么也沒有:

package com.test.scope.si; /** * @Description:有3個(gè) AccoutDao 的援用,他們的scope順次為默許、單例(singleton)、原型( prototype) * 省略的get set方法 */ public class Client1 { private AccoutDao accoutDao; private AccoutDao accoutDaob; private AccoutDao accoutDaoc; @Override public String toString() { return "Client1 [accoutDao=" + accoutDao + ", accoutDaob=" + accoutDaob + ", accoutDaoc=" + accoutDaoc + "]"; } }

下面是配置文件:

<?xml version="1.0" encoding="UTF⑻"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 定義3個(gè) AccoutDao bean 順次為默許配置 單例原型 --> <bean id="account1" class="com.test.scope.si.AccoutDao"></bean> <bean id="account2" class="com.test.scope.si.AccoutDao" scope="singleton"></bean> <bean id="account3" class="com.test.scope.si.AccoutDao" scope="prototype"></bean> <!-- 定義 Client1 bean 和 Client2 bean 他們的定義完全1樣,這里只是為了說明 singleton 和 prototype 區(qū)分 他們都有3個(gè)依賴,分別是以上定義的bean --> <bean id ="c1a" class="com.test.scope.si.Client1"> <property name="accoutDao" ref="account1"></property> <property name="accoutDaob" ref="account2"></property> <property name="accoutDaoc" ref="account3"></property> </bean> <bean id ="c2a" class="com.test.scope.si.Client2"> <property name="accoutDao" ref="account1"></property> <property name="accoutDaob" ref="account2"></property> <property name="accoutDaoc" ref="account3"></property> </bean> </beans>


下面是測(cè)試程序:

package com.test.scope; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestMain { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("allbean.xml"); //測(cè)試scope為singleton 和prototype 區(qū)分,以下3個(gè)bean的定義順次為默許、singleton 和 prototype 。 //注意 打印的值和后邊的 c1a和 c2a的相同和不同的地方 System.out.println(context.getBean("account1")); System.out.println(context.getBean("account2")); System.out.println(context.getBean("account3")); //注意以下的不同的地方,可以看到accoutDaoc 的值總是不1樣的。而其他的與上面的打印保持1致。 System.out.println(context.getBean("c1a")); System.out.println(context.getBean("c2a")); } }

測(cè)試結(jié)果,符合預(yù)期:

其他Scope

除以上兩種scope,還有request, session和global session3種scope,他們用于web環(huán)境中,否則將拋出異常。

其bean的scope和以上類似,不同的是他們的意義。意義見開頭的扼要說明,具體的代碼例子見下節(jié),下面說下以上3種scope的測(cè)試環(huán)境。

要測(cè)試這3種scope需要使用web項(xiàng)目,web項(xiàng)目部署較為復(fù)雜,本文依照spring官方文檔和網(wǎng)上的1些資料,把spring和servlet整合,做簡(jiǎn)單的測(cè)試,下面的配置是 web.xml中配置。然后相應(yīng)的servlet在init方法中從容器中取得依賴:

<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/classes/webAllbean.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener>

Servlet中的init方法中手動(dòng)注入依賴:

public void init(ServletConfig config) throws ServletException { // TODO Auto-generatedmethod stub super.init(config); WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(this .getServletContext()); c = applicationContext.getBean("c3a", Client3.class); System.out.println("iniiiiiii-------------"); }


注:需要引入aop的相干依賴包。

還有1些其他的方法:

Servlet代理:http://blog.csdn.net/xwl617756974/article/details/7451773

支持autowire的servlet: http://www.tuicool.com/articles/32U3Qr

另外關(guān)于Spring的作用域和RequestContextListener作用

不同scope依賴

Spring容器中各個(gè)bean中可能存在依賴,而且相互依賴的bean之間的scope可能也不同。不同的scope之間的依賴可能會(huì)出現(xiàn)問題。主要是以下兩種:

singleton 依賴prototype;

reques、session、application作為依賴。

singleton 依賴prototype

依賴無(wú)處不在,當(dāng)這類情況出現(xiàn)的時(shí)候,由于singleton 只實(shí)例化1次,所以其所依賴的prototype 的bean也只有1次被被設(shè)置依賴的機(jī)會(huì)。這有時(shí)不是我們想要的。

假定 A的scope為singleton,B的scope為prototype ,A依賴B。在調(diào)用A的某些方法時(shí),需要全新的B的協(xié)作。因而bean定義依賴的方法就會(huì)出現(xiàn)問題。

有3種種解決方案:

Spring接口手動(dòng)注入

在調(diào)用相干方法的時(shí)候,手動(dòng)重新注入prototype的bean,這類方法可讓bean實(shí)現(xiàn)ApplicationContextAware 接口,獲得spring容器的援用,從中獲得bean。這樣做的壞處是和spring的接口耦合在了1起。示例代碼以下:

定義了1個(gè)全新的類ClientForSp,里面的方法testOne和testTwo都是打印本身,不同的是testOne做了重新注入的處理,有兩個(gè)AccoutDao類型的prototype依賴用來比較,AccoutDao和以上相同:

package com.test.scope.sid; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import com.test.scope.si.AccoutDao; /** * @Description:測(cè)試 singleton依賴prototype ,實(shí)現(xiàn)ApplicationContextAware接口,獲得bean工廠的援用 * 兩個(gè)依賴字段均為prototype, * 方法testOne 和 testTwo 均需要依賴字段的協(xié)助。 * 方法testOne 每次調(diào)用重新獲得bean,故每次都是全新的bean。 * 方法testTwo則不是。 * */ public class ClientForSp implements ApplicationContextAware{ private AccoutDao accoutDao; private AccoutDao accoutDao1; private ApplicationContext context; public void testOne(){ this.setAccoutDao(createAccountDao()); System.out.println(this); } public void testTwo(){ System.out.println(this); } public AccoutDao getAccoutDao() { return accoutDao; } public void setAccoutDao(AccoutDao accoutDao) { this.accoutDao = accoutDao; } public AccoutDao getAccoutDao1() { return accoutDao1; } public void setAccoutDao1(AccoutDao accoutDao1) { this.accoutDao1 = accoutDao1; } public AccoutDao createAccountDao(){ return context.getBean("account3", AccoutDao.class); } @Override public String toString() { return "ClientForSp [accoutDao=" + accoutDao + ", accoutDao1=" + accoutDao1 + "]"; } @Override public void setApplicationContext(ApplicationContext arg0) throws BeansException { this.context = arg0; } }

配置文件以下:

<!-- 定義 ClientForSp 依賴兩個(gè) prototype的bean,但在ClientForSp方法testOne中利用spring接口手動(dòng)注入--> <bean id ="csp1" class="com.test.scope.sid.ClientForSp"> <property name="accoutDao" ref="account3"></property> <property name="accoutDao1" ref="account3"></property> </bean>


測(cè)試代碼以下,首先調(diào)用兩次testTwo方法(沒有重新注入依賴),然后調(diào)用testOne方法(重新注入了依賴):

ClientForSp sp1 = context.getBean("csp1", ClientForSp.class); sp1.testTwo(); sp1.testTwo(); System.out.println(); sp1.testOne(); sp1.testOne();


測(cè)試結(jié)果以下,兩次調(diào)用testTwo方法的打印完全1樣,而后調(diào)用testOne方法可以看到accoutDao的援用每次都不1樣,符合預(yù)期:


Lookup methodinjection

spring容器可以通過查找其所管理的已命名的bean作為返回值,來覆蓋(override)其所管理的bean的某個(gè)方法(查找到的bean作為bean的返回值)。利用這點(diǎn)可以解決以上問題。方法覆蓋采取動(dòng)態(tài)生成字節(jié)碼的情勢(shì)。被覆蓋的方法可以是抽象的,也能夠是非抽象的,需要沒有任何參數(shù)。

方法簽名以下:

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

解決以上問題,需要使用bean標(biāo)簽的<lookup-method>子標(biāo)簽,示例代碼和以上類似,只有配置不同,配置以下:

<!-- 定義 ClientForSp ,依賴兩個(gè) prototype的bean,采取 lookup-method方法,在每次調(diào)用testOne時(shí),重新注入新的prototype bean --> <bean id ="csp2" class="com.test.scope.sid.ClientForSp"> <lookup-method name="createAccountDao" bean="account3"/> <property name="accoutDao1" ref="account3"></property> </bean>

測(cè)試代碼和結(jié)果不再贅述。

Arbitrary methodreplacement

這是1個(gè)不太經(jīng)常使用的方法。需要額外的1個(gè)類實(shí)現(xiàn)MethodReplacer接口,故名思議,用來做方法替換的。

另外需要使用bean標(biāo)簽的<lookup-method>子標(biāo)簽<replaced-method>,示例代碼和以上類似,注意配置和MethodReplacer的實(shí)現(xiàn):

<!-- 定義 ClientForSp ,依賴兩個(gè) prototype的bean,采取 replaced-method方法,強(qiáng)迫替換掉 createAccountDao 方法--> <bean id ="csp3" class="com.test.scope.sid.ClientForSp"> <replaced-method name="createAccountDao" replacer="myReplacer"></replaced-method> <property name="accoutDao" ref="account3"></property> <property name="accoutDao1" ref="account3"></property> </bean> <bean id ="myReplacer" class="com.test.scope.sid.MyAccountCreateor"/>

 

public class MyAccountCreateor implements MethodReplacer { /** * 參數(shù)的意思分別是原被調(diào)用的方法對(duì)象、方法和參數(shù) */ @Override public Object reimplement(Object arg0, Method arg1, Object[] arg2) throws Throwable { System.out.println("replaced"); return new AccoutDao(); } }


測(cè)試代碼和分析不在贅述。

reques、session、application作為依賴。

當(dāng)scope為 request, session, globalSession的bean作為依賴注入到其他范圍內(nèi)的bean中時(shí),會(huì)產(chǎn)生類似singleton依賴prototype的問題。這類情況下只要使用bean的子標(biāo)簽<aop:scoped-proxy/> 便可。

以下:

<!-- an HTTP request bean exposed as a proxy --> <bean id="account4" class="com.test.scope.si.AccoutDao" scope="request"> <!-- instructs the container to proxy the surrounding bean --> <aop:scoped-proxy/> </bean> <!-- a singleton-scoped bean injected with the above beans --> <bean id ="c3a" class="com.test.scope.si.Client3"> <property name="accoutDao" ref="account4"></property> </bean>

雖然代碼很簡(jiǎn)單,但是要理解這個(gè)問題。由于c3a的scope為singleton,所以它只被初始化1次,它的依賴accoutDao的scope雖然是request,也只被注入1次,當(dāng)是不同httpRequest到來是,bean “c3a”的accoutDao依賴總是不變的,這肯定是毛病的。所以加上<aop:scoped-proxy/>子標(biāo)簽,告知spring容器采取aop代理為不同request生成不同的accoutDao對(duì)象。1般采取動(dòng)態(tài)生成字節(jié)碼的技術(shù)。如果不使用<aop:scoped-proxy/>標(biāo)簽,則啟動(dòng)時(shí)報(bào)錯(cuò)。

下面使用具體的代碼演示 request、session 的scope 使用Aop代理前后的區(qū)分。代碼需要web環(huán)境,環(huán)境的部署見上文。這里配置1個(gè)bean具有兩個(gè)依賴,順次為requset代理,session代理。

配置以下:

<!-- an HTTP request bean exposed as a proxy --> <bean id="account4" class="com.test.scope.si.AccoutDao" scope="request"> <!-- instructs the container to proxy the surrounding bean --> <aop:scoped-proxy/> </bean> <!-- an HTTP session bean exposed as a proxy --> <bean id="account5" class="com.test.scope.si.AccoutDao" scope="session"> <!-- instructs the container to proxy the surrounding bean --> <aop:scoped-proxy/> </bean> <!-- a singleton-scoped bean injected with the above beans --> <bean id ="c3a" class="com.test.scope.si.Client3"> <property name="accoutDao" ref="account4"></property> <property name="accoutDao1" ref="account5"></property> </bean>


類client3試試是1個(gè)標(biāo)準(zhǔn)的javabean,兩個(gè)字段和以上的依賴對(duì)應(yīng),這里不贅述。測(cè)試代碼在1個(gè)servlet中,以下是它的doget方法:

if (c != null) { System.out.println("request代理每次都不1樣"+c.getAccoutDao()); System.out.println("session代理不同會(huì)話不1樣"+c.getAccoutDao1()); } else { System.out.println("null"); }
把以上代碼部署到tomcat中,然后分別用不同的閱讀器各訪問兩次,不同的閱讀器來摹擬不同的session,測(cè)試結(jié)果以下:


以上測(cè)試結(jié)果是先用電腦閱讀器訪問兩次,在用手機(jī)閱讀器訪問兩次。首先,每次訪問request依賴的值都不1樣。其次,相同閱讀器的session依賴1樣,不同閱讀器不1樣。以上符合預(yù)期結(jié)果。

結(jié)束

本篇文章較為詳細(xì)了介紹了spring bean的scope屬性,文中有詳細(xì)的示例測(cè)試代碼。從scope到不同的scope之間的依賴關(guān)系,特別是在說明有關(guān)web的scope的時(shí)候,本人花費(fèi)了較多的時(shí)間來部署環(huán)境。關(guān)于scope還缺少自定義scope的部份,暫且不討論。期待大家共同進(jìn)步。本文演示代碼下載地址

生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 免费观看的男女羞羞视频 | 在线中文字幕视频 | 国产一级做a爰片... | 日韩精品亚洲精品485页 | 性欧美性free| 欧美性色黄大片www喷水 | xxx国产精品 | 亚洲国产精品一区二区三区 | 亚洲成人一级 | 欧美精品国产一区二区三区 | 不卡精品国产_亚洲人成在线 | 婷婷五月在线视频 | 亚洲国产成人久久笫一页 | 逼逼网站| 亚洲欧美高清 | 欧美精品在线播放 | 亚洲视频一二区 | 久久久久久国产精品视频 | 18岁禁免费网站 | 日本女人一级片 | 国产精品亚洲综合第一区 | 欧美日本一道免费一区三区 | 国产三级在线观看视频 | 欧美日韩在线观看免费 | 在线视频h| 最近免费中文字幕视频高清在线看 | 国产毛片一区二区 | 免费观看性欧美特黄 | 欧美高清3dfreexxxx性 | 麻豆影视在线最新免费观看 | 国产第一页在线视频 | 午夜精品久久久 | 日本欧美一区二区三区片 | 欧美日韩国产综合在线小说 | 国产一区二区三区欧美精品 | 女人色图 | 黄色的网站免费观看 | 亚洲第一色站 | 亚洲免费视频播放 | 亚洲最大的黄色网址 | 欧美色伊人 |