![依賴關(guān)系以及注入實現(xiàn)_第1頁](http://file4.renrendoc.com/view/9e8c78523d7b8e27231f2601183edfb9/9e8c78523d7b8e27231f2601183edfb91.gif)
![依賴關(guān)系以及注入實現(xiàn)_第2頁](http://file4.renrendoc.com/view/9e8c78523d7b8e27231f2601183edfb9/9e8c78523d7b8e27231f2601183edfb92.gif)
![依賴關(guān)系以及注入實現(xiàn)_第3頁](http://file4.renrendoc.com/view/9e8c78523d7b8e27231f2601183edfb9/9e8c78523d7b8e27231f2601183edfb93.gif)
![依賴關(guān)系以及注入實現(xiàn)_第4頁](http://file4.renrendoc.com/view/9e8c78523d7b8e27231f2601183edfb9/9e8c78523d7b8e27231f2601183edfb94.gif)
![依賴關(guān)系以及注入實現(xiàn)_第5頁](http://file4.renrendoc.com/view/9e8c78523d7b8e27231f2601183edfb9/9e8c78523d7b8e27231f2601183edfb95.gif)
下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
Copyright2008ByNeusoftGroup.Allrightsreserved第三章
依賴關(guān)系以及依賴注入的實現(xiàn)
Copyright2009ByNeusoftGroup.Allrightsreserved
典型的企業(yè)應(yīng)用不會只由單一的對象(或bean)組成。毫無疑問,即使最簡單的系統(tǒng)也需要多個對象一起來滿足最終用戶的需求。接下來的的內(nèi)容除了闡述如何單獨定義一系列bean外,還將描述如何讓這些bean對象一起協(xié)同工作來實現(xiàn)一個完整的真實應(yīng)用??刂品崔D(zhuǎn)(InversionofControl,IoC)與
依賴注入(DependencyInjection,DI)
依賴注入背后的基本原理是對象之間的依賴關(guān)系(即一起工作的其它對象)。因此,容器的工作就是創(chuàng)建bean時注入那些依賴關(guān)系。相對于由bean自己來控制其實例化、直接在構(gòu)造器中指定依賴關(guān)系或者類似服務(wù)定位器(ServiceLocator)模式這3種自主控制依賴關(guān)系注入的方法來說,控制從根本上發(fā)生了倒轉(zhuǎn),這也正是控制反轉(zhuǎn)(InversionofControl,IoC)名字的由來。應(yīng)用DI原則后,代碼將更加清晰。而且當bean自己不再擔心對象之間的依賴關(guān)系(以及在何時何地指定這種依賴關(guān)系和依賴的實際類是什么)之后,實現(xiàn)更高層次的松耦合將易如反掌。DI主要有兩種注入方式,即Setter方法注入和構(gòu)造器注入。要強調(diào)并再一次明確的是:由容器來管理對象之間的依賴關(guān)系,而不是對象本身來管理Spring框架的基本思想就是IoC/DI。Spring就是一個IoC容器。IoC和DI其實是一回事,但DI更能表達這種設(shè)計模式的思想。所謂的依賴注入就是容器將我們需要的屬性對象等實例化好后,主動的提供給我們使用,我們只要在相關(guān)的類中提供屬性對象對應(yīng)的setter方法或是構(gòu)造方法即可,這樣就可以注入進來。這樣的好處是我們這樣的類沒有主動的依賴于那些屬性對象。Spring的沒有侵入性特征也是體現(xiàn)在DI:我們只要提供標準的setter方法或是標準的構(gòu)造方法,那么容器就能將我們需要的屬性對象實例化好并主動注入經(jīng)來。控制反轉(zhuǎn)(InversionofControl,IoC)與
依賴注入(DependencyInjection,DI)
控制反轉(zhuǎn)(InversionofControl,IoC)與
依賴注入(DependencyInjection,DI)
IoC容器的關(guān)鍵點:
1、必須將被管理的對象定義在Spring的配置文件中; 2、必須定義構(gòu)造函數(shù)或setter方法,讓spring將對象注入過來;
Setter注入通過調(diào)用無參構(gòu)造器或無參static工廠方法實例化bean之后,調(diào)用該bean的setter方法,即可實現(xiàn)基于setter的DI。下面的例子將展示使用setter注入依賴。注意,這個類并沒有什么特別之處,它就是普通的Java類。
public
classProdsManagerImplimplementsProdsManagerIface{privateProdsDaoIfaceprodsDao;/*利用spring,通過setter方法,將本類所依賴的屬性對象注入進來,這里的屬性名稱,務(wù)必要與配置文件中的名稱相同。 */ public
voidsetProdsDao(ProdsDaoIfaceprodsDao){ dsDao=prodsDao; } //在業(yè)務(wù)層調(diào)用了被注入進來的Dao層對象的方法,進行工作。
publicListfindAllProducts(){ Listlist=prodsDao.findAllProducts(); returnlist;}}構(gòu)造器注入-1基于構(gòu)造器的DI通過調(diào)用帶參數(shù)的構(gòu)造器來實現(xiàn),每個參數(shù)代表著一個協(xié)作者。下面展示了使用構(gòu)造器參數(shù)來注入依賴關(guān)系的例子。再次提醒,這個類并沒有什么特別之處。public
classUserServiceWithConstructorImplimplementsUserServiceIface{privateUserDaoIfaceuserDao;publicUserServiceWithConstructorImpl(UserDaoIfaceuserDao){this.userDao=userDao;}public
booleanvalidateLogin(Stringid,Stringpwd){userDao.login(id,pwd);return
true;}}那么配置文件中應(yīng)當如何體現(xiàn)?如下:<beansxmlns=""xmlns:xsi=""xmlns:aop=""/schema/tx><!--definitethedao--><beanid="userDao4Oracle" class="com.neusoft.dao.impl.UserDao4Oracle9Impl"/><beanid="userDao4DB2" class="com.neusoft.dao.impl.UserDao4DB2Impl"/><!--definitetheservice--><beanid="login_serviceUseCons" class="com.neusoft.service.impl.UserServiceWithConstructorImpl"><constructor-argref="userDao4Oracle"/></bean><beanid="login_serviceUseSetters" class="com.neusoft.service.impl.UserServiceWithSettersImpl"><propertyname="userDao"ref="userDao4DB2“/></bean></beans>構(gòu)造器注入-1構(gòu)造器注入-2BeanFactory對于它所管理的bean提供兩種注入依賴方式(實際上它也支持同時使用構(gòu)造器注入和Setter方式注入依賴)。大部份的Spring用戶并不需要直接以編程的方式處理這些類,而是采用XML的方式來進行定義,在內(nèi)部這些定義將被轉(zhuǎn)換成相應(yīng)類的實例,并最終得到一個SpringIoC容器實例。處理bean依賴關(guān)系通常按以下步驟進行:根據(jù)定義bean的配置(文件)創(chuàng)建并初始化BeanFactory實例(大部份的Spring用戶使用支持XML格式配置文件的BeanFactory或ApplicationContext實現(xiàn))。每個bean的依賴將以屬性、構(gòu)造器參數(shù)、或靜態(tài)工廠方法參數(shù)的形式出現(xiàn)。當這些bean被實際創(chuàng)建時,這些依賴也將會提供給該bean。每個屬性或構(gòu)造器參數(shù)既可以是一個實際的值,也可以是對該容器中另一個bean的引用。每個指定的屬性或構(gòu)造器參數(shù)值必須能夠被轉(zhuǎn)換成屬性或構(gòu)造參數(shù)所需的類型。默認情況下,Spring會能夠以String類型提供值轉(zhuǎn)換成各種內(nèi)置類型,比如int、long、String、boolean等。構(gòu)造器注入-3需要強調(diào)的一點就是,Spring會在容器被創(chuàng)建時驗證容器中每個bean的配置,包括驗證那些bean所引用的屬性是否指向一個有效的bean(即被引用的bean也在容器中被定義)。然而,在bean被實際創(chuàng)建之前,bean的屬性并不會被設(shè)置。對于那些singleton類型和被設(shè)置為提前實例化的bean(比如ApplicationContext中的singletonbean)而言,bean實例將與容器同時被創(chuàng)建。而另外一些bean則會在需要的時候被創(chuàng)建,伴隨著bean被實際創(chuàng)建,作為該bean的依賴bean以及依賴bean的依賴bean(依此類推)也將被創(chuàng)建和分配。通常情況下,我們可以信賴Spring,它會在容器加載時發(fā)現(xiàn)配置錯誤(比如對無效bean的引用以及循環(huán)依賴)。Spring會在bean創(chuàng)建的時候才去設(shè)置屬性和依賴關(guān)系(只在需要時創(chuàng)建所依賴的其他對象)。Spring容器被正確加載之后,當獲取一個bean實例時,如果在創(chuàng)建bean或者設(shè)置依賴時出現(xiàn)問題,那么將拋出一個異常。因缺少或設(shè)置了一個無效屬性而導致拋出一個異常的情況的確是存在的。因為一些配置問題而導致潛在的可見性被延遲,所以在默認情況下,ApplicationContext實現(xiàn)中的bean采用提前實例化的singleton模式。在實際需要之前創(chuàng)建這些bean將帶來時間與內(nèi)存的開銷。而這樣做的好處就是ApplicationContext被加載的時候可以盡早的發(fā)現(xiàn)一些配置的問題。不過用戶也可以根據(jù)需要采用延遲實例化來替代默認的singleton模式。何謂循環(huán)依賴?構(gòu)造器注入-3構(gòu)造器注入-4最后,還要提到的一點就是,當協(xié)作bean被注入到依賴bean時,協(xié)作bean必須在依賴bean之前完全配置好。例如beanA對beanB存在依賴關(guān)系,那么SpringIoC容器在調(diào)用beanA的setter方法之前,beanB必須被完全配置,這里所謂完全配置的意思就是bean將被實例化(如果不是采用提前實例化的singleton模式),相關(guān)的依賴也將被設(shè)置好。如何在構(gòu)造器注入和Setter注入之間進行選擇?bean的配置形式及構(gòu)造器參數(shù)-基本類型 bean的屬性及構(gòu)造器參數(shù)既可以引用容器中的其他bean,也可以是內(nèi)聯(lián)(在spring的XML配置中使用<property/>和<constructor-arg/>元素定義)bean。直接量(基本類型、Strings類型等。)<value/>元素:通過字符串來指定屬性或構(gòu)造器參數(shù)的值。JavaBeanPropertyEditor將用于把字符串從java.lang.String類型轉(zhuǎn)化為實際的屬性或參數(shù)類型。<beanid="myDataSource"destroy-method="close" class="mons.dbcp.BasicDataSource"><propertyname="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property><propertyname="url"> <value>jdbc:mysql://localhost:3306/mydb</value></property><propertyname="username"><value>root</value></property></bean>示例spring-injectionVjectbean的配置形式及構(gòu)造器參數(shù)-基本類型直接量(基本類型、Strings類型等。)
<idref/>元素:用來將容器內(nèi)其它bean的id傳給<constructor-arg/>或<property/>元素,同時提供錯誤驗證功能。<beanid="theTargetBean"class="..."/><beanid="theClientBean"class="..."><propertyname="targetName"><idref
bean="theTargetBean"/></property></bean>bean的配置形式及構(gòu)造器參數(shù)-基本類型上述bean定義片段完全地等同于(在運行時)以下的片段:<beanid="theTargetBean"class="..."/><beanid="client"class="..."><propertyname="targetName"><value>theTargetBean</value>
</property></bean>第一種形式比第二種更可?。ean的配置形式及構(gòu)造器參數(shù)-基本類型引用其它的bean(協(xié)作者)
在<constructor-arg/>或<property/>元素內(nèi)部還可以使用ref元素。該元素用來將bean中指定屬性的值設(shè)置為對容器中的另外一個bean的引用。 該引用bean將被作為依賴注入,而且在注入之前會被初始化(如果是singletonbean則已被容器初始化)。盡管都是對另外一個對象的引用,但是通過id/name指向另外一個對象卻有三種不同的形式,不同的形式將決定如何處理作用域及驗證。 示例spring-injectionVjectbean的配置形式及構(gòu)造器參數(shù)-基本類型第一種形式:也是最常見的形式是通過使用<ref/>標記指定bean屬性的目標bean,通過該標簽可以引用同一容器或父容器內(nèi)的任何bean(無論是否在同一XML文件中)。XML‘bean’元素的值既可以是指定bean的id值也可以是其name值。<refbean="someBean"/>第二種形式:是使用ref的local屬性指定目標bean,它可以利用XML解析器來驗證所引用的bean是否存在同一文件中。local屬性值必須是目標bean的id屬性值。如果在同一配置文件中沒有找到引用的bean,XML解析器將拋出一個例外。如果目標bean是在同一文件內(nèi),使用local方式就是最好的選擇(為了盡早地發(fā)現(xiàn)錯誤)。<reflocal="someBean"/>bean的配置形式及構(gòu)造器參數(shù)-基本類型第三種方式是通過使用ref的parent屬性來引用當前容器的父容器中的bean。parent屬性值既可以是目標bean的id值,也可以是name屬性值。而且目標bean必須在當前容器的父容器中。使用parent屬性的主要用途是為了用某個與父容器中的bean同名的代理來包裝父容器中的一個bean(例如,子上下文中的一個bean定義覆蓋了他的父bean)。 示例如下:bean的配置形式及構(gòu)造器參數(shù)-基本類型<!--intheparentcontext-->
<beanid="accountService"class="com.foo.SimpleAccountService">
<!--insertdependenciesasrequiredashere-->
</bean><!--inthechild(descendant)context-->
<--noticethatthenameofthisbeanisthesameasthenameofthe‘parent’bean-->
<beanid="accountService" class="org.springframework.aop.framework.ProxyFactoryBean"> <propertyname="target"> <refparent="accountService"/>
<!--noticehowwerefertotheparentbean-->
</property>
<!--insertotherconfigurationanddependenciesasrequiredashere-->
</bean>('parent'屬性的使用并不常見。)bean的配置形式及構(gòu)造器參數(shù)-基本類型通過<list/>、<set/>、<map/>及<props/>元素可以定義和設(shè)置與JavaCollection類型對應(yīng)List、Set、Map及Properties的值。注意:map的key或value值,或set的value值不能是以下元素
bean|ref|idref|list|set|map|props|value|null示例spring-injectionVjectbean的配置形式及構(gòu)造器參數(shù)-集合<beanid="plexObject"class="plexObject"><!--resultsinasetAdminEmails(java.util.Properties)call--><propertyname="adminEmails"><props><propkey="administrator"></prop><propkey="support"></prop><propkey="development"></prop></props></property><!--resultsinasetSomeList(java.util.List)call--><propertyname="someList"><list><value>alistelementfollowedbyareference</value><refbean="myDataSource"/></list></property>bean的配置形式及構(gòu)造器參數(shù)-集合<!--resultsinasetSomeMap(java.util.Map)call-->
<propertyname="someMap"><map><entry><key><value>yupanentry</value></key><value>justsomestring</value></entry><entry><key><value>yuparef</value></key><refbean="myDataSource"/></entry></map></property><!--resultsinasetSomeSet(java.util.Set)call-->
<propertyname="someSet"><set><value>justsomestring</value><refbean="myDataSource"/></set></property></bean>bean的配置形式及構(gòu)造器參數(shù)-集合強類型集合(僅適用于Java5+)如果使用Java5(Tiger),那么你可以使用強類型集合。比如,聲明一個只能包含String類型元素的Collection。假若使用Spring來給bean注入強類型的Collection,那就可以利用Spring的類型轉(zhuǎn)換功能,當向強類型Collection中添加元素前,這些元素將被轉(zhuǎn)換。用一個例子加以說明??紤]以下的類定義,及其相應(yīng)的(XML)配置...。
publicclassFoo{ privateMap<String,Float>accounts; publicvoidsetAccounts(Map<String,Float>accounts){ this.accounts=accounts; } }
接下頁:bean的配置形式及構(gòu)造器參數(shù)-集合 <beans> <beanid="foo"class="x.y.Foo">
<propertyname="accounts"> <map> <entrykey="one"value="9.99"/> <entrykey="two"value="2.75"/> <entrykey="six"value="3.99"/> </map> </property> </bean> </beans>
在foobean的accounts屬性被注入之前,通過反射,利用強類型Map<String,Float>的泛型信息,Spring的底層類型轉(zhuǎn)換機制將會把各種value元素值轉(zhuǎn)換為Float類型,因此字符串9.99、2.75及3.99就會被轉(zhuǎn)換為實際的Float類型。bean的配置形式及構(gòu)造器參數(shù)-集合
Nulls值的處理
<null/>用于處理null值。Spring會把屬性的空參數(shù)當作空字符串處理。以下的xml片斷將email屬性設(shè)為空字符串。<beanclass="ExampleBean"><propertyname="email"> <value></value></property></bean>這等同于Java代碼:exampleBean.setEmail(“”)。而null值則可以使用<null>元素可用來表示。例如:<beanclass="ExampleBean"><propertyname="email"> <null/></property></bean>上述的配置等同于Java代碼:exampleBean.setEmail(null)。bean的配置形式及構(gòu)造器參數(shù)-集合XML-basedconfigurationmetadatashortcuts(1)
針對常見的value值或bean的引用,Spring提供了簡化格式用于替代<value/>和<ref/>元素。<property/>、<constructor-arg/>及<entry/>元素都支持value屬性(attribute),它可以用來替代內(nèi)嵌的<value/>元素。因而,以下的代碼:
<propertyname="myProperty"> <value>hello</value> </property> <constructor-arg> <value>hello</value> </constructor-arg> <entrykey="myKey"> <value>hello</value> </entry>
等同于:
<propertyname="myProperty"value="hello"/> <constructor-argvalue="hello"/> <entrykey="myKey"value="hello"/>
通常情況下,當手工編寫配置文件時,你可能會偏向于使用簡寫形式(Spring的開發(fā)團隊就是這么做的)。bean的配置形式及構(gòu)造器參數(shù)-集合XML-basedconfigurationmetadatashortcuts(2)
<property/>和<constructor-arg/>支持類似的簡寫屬性ref,它可能用來替代整個內(nèi)嵌的<ref/>元素。因而,以下的代碼:
<propertyname="myProperty"> <refbean="myBean"> </property> <constructor-arg> <refbean="myBean"> </constructor-arg>
等同于:
<propertyname="myProperty"ref="myBean"/> <constructor-argref="myBean"/>
bean的配置形式及構(gòu)造器參數(shù)-集合
注意,盡管存在等同于<refbean="xxx">元素的簡寫形式,但并沒有<reflocal="xxx">的簡寫形式,為了對當前xml中bean的引用,你只能使用完整的形式。 最后,map中entry元素的簡寫形式為key/key-ref和value/value-ref屬性,因而,以下的代碼:
<entry> <key> <refbean="myKeyBean"/> </key> <refbean="myValueBean"/> </entry>
等同于:
<entrykey-ref="myKeyBean"value-ref="myValueBean"/>
再次強調(diào),只有<refbean="xxx">元素的簡寫形式,沒有<reflocal="xxx">的簡寫形式。bean的配置形式及構(gòu)造器參數(shù)-集合多數(shù)情況下,一個bean對另一個bean的依賴最簡單的做法就是將一個bean設(shè)置為另外一個bean的屬性。在xml配置文件中最常見的就是使用<ref/>元素。有時候它還有另外一種變體,如果一個bean能感知IoC容器,只要給出它所依賴的id,那么就可以通過編程的方式從容器中取得它所依賴的對象。無論采用哪一種方法,被依賴bean將在依賴bean之前被適當?shù)某跏蓟T谏贁?shù)情況下,有時候bean之間的依賴關(guān)系并不是那么的直接(例如,當類中的靜態(tài)塊的被初始化時,如數(shù)據(jù)庫驅(qū)動的注冊)。depends-on屬性可以用于當前bean初始化之前顯式地強制一個或多個bean被初始化。下面的例子中使用了depends-on屬性來指定一個bean的依賴。bean的配置形式及構(gòu)造器參數(shù)-(depends-on)
<beanid="beanOne"class="ExampleBean"depends-on="manager"/> <beanid="manager"class="ManagerBean"/>
若需要表達對多個bean的依賴,可以在‘depends-on’中將指定的多個bean名字用分隔符進行分隔,分隔符可以是逗號、空格及分號等。下面的例子中使用了‘depends-on’來表達對多個bean的依賴。
<beanid="beanOne"class="ExampleBean" dependson="manager,accountDao"> <propertyname="manager"ref="manager"/> </bean> <beanid="manager"class="ManagerBean"/> <beanid="accountDao"class="x.y.jdbc.JdbcAccountDao"/>
bean的配置形式及構(gòu)造器參數(shù)-(depends-on)ApplicationContext實現(xiàn)的默認行為就是在啟動時將所有singletonbean提前進行實例化。提前實例化意味著作為初始化過程的一部分,ApplicationContext實例會創(chuàng)建并配置所有的singletonbean。通常情況下這是件好事,因為這樣在配置中的任何錯誤就會即刻被發(fā)現(xiàn)(否則的話可能要花幾個小時甚至幾天)。有時候這種默認處理可能并不是你想要的。如果你不想讓一個singletonbean在ApplicationContext實現(xiàn)在初始化時被提前實例化,那么可以將bean設(shè)置為延遲實例化。一個延遲初始化bean將告訴IoC容器是在啟動時還是在第一次被用到時實例化。在XML配置文件中,延遲初始化將通過<bean/>元素中的lazy-init屬性來進行控制。例如:
<beanid="lazy"class="com.foo.ExpensiveToCreateBean"lazy-init="true"> <!--variouspropertieshere...-->
</bean> <beanname="not.lazy"class="com.foo.AnotherBean">
<!--variouspropertieshere...-->
</bean>
bean的配置形式及構(gòu)造器參數(shù)-延遲初始化bean當ApplicationContext實現(xiàn)加載上述配置時,設(shè)置為lazy的bean將不會在ApplicationContext啟動時提前被實例化,而not.lazy卻會被提前實例化。需要說明的是,如果一個bean被設(shè)置為延遲初始化,而另一個非延遲初始化的singletonbean依賴于它,那么當ApplicationContext提前實例化singletonbean時,它必須也確保所有上述singleton依賴bean也被預(yù)先初始化,當然也包括設(shè)置為延遲實例化的bean。因此,如果Ioc容器在啟動的時候創(chuàng)建了那些設(shè)置為延遲實例化的bean的實例,你也不要覺得奇怪,因為那些延遲初始化的bean可能在配置的某個地方被注入到了一個非延遲初始化singletonbean里面。bean的配置形式及構(gòu)造器參數(shù)-延遲初始化bean自動裝配(autowire)SpringIoC容器可以自動裝配(autowire)相互協(xié)作bean之間的關(guān)聯(lián)關(guān)系。因此,如果可能的話,可以自動讓Spring通過檢查BeanFactory中的內(nèi)容,來替我們指定bean的協(xié)作者(其他被依賴的bean)。由于autowire可以針對單個bean進行設(shè)置,因此可以讓有些bean使用autowire,有些bean不采用。autowire的方便之處在減少或者消除屬性或構(gòu)造器參數(shù)的設(shè)置,這樣可以給我們的配置文件減減肥!在xml配置文件中,autowire一共有五種類型,可以在<bean/>元素中使用autowire屬性指定:
注意:約定由于配置的原則,即各個bean中屬性的命名與配置文件中的id的值要一致。還有一點就是要在配置文件的頭部聲明部分加入:
default-autowire=“byName”、default-autowire=“byType”
開發(fā)期間建議使用這個方式;而項目完成后穩(wěn)定期,不建議使用。因為在維護升級時,我們難以查詢bean之間的依賴關(guān)系。見如下示例:spring-autowireByNjectspring-autowireByTject
依賴檢查Spring除了能對容器中bean的依賴設(shè)置進行檢查外。還可以檢查bean定義中實際屬性值的設(shè)置,當然也包括采用自動裝配方式設(shè)置屬性值的檢查。當需要確保bean的所有屬性值(或者屬性類型)被正確設(shè)置的時候,那么這個功能會非常有用。當然,在很多情況下,bean類的某些屬性會具有默認值,或者有些屬性并不會在所有場景下使用,因此這項功能會存在一定的局限性。就像自動裝配一樣,依賴檢查也可以針對每一個bean進行設(shè)置。依賴檢查默認為not,它有幾種不同的使用模式,在xml配置文件中,可以在bean定義中為dependency-check屬性使用以下幾種值:依賴檢查bean的作用域
在創(chuàng)建一個bean定義(通常為XML配置文件)時,你可以簡單的將其理解為:用以創(chuàng)建由該bean定義所決定的實際對象實例的一張“處方(recipe)”或者模板。就如class一樣,根據(jù)一張“處方”你可以創(chuàng)建多個對象實例。你不僅可以控制注入到對象(bean定義)中的各種依賴和配置值,還可以控制該對象的作用域。這樣你可以靈活選擇所建對象的作用域,而不必在JavaClass級定義作用域。 -使用singleton,每次調(diào)用getBean()時返回相同的實例; -使用prototype,每次調(diào)用getBean()時返回不相同的實例;比如,在用Spring集成Struts時,我們將action的創(chuàng)建交給Spring來創(chuàng)建,就可以使用prototype,這樣使得每次過來一個線程時都給你一個不同的action實例,以避免線程安全的問題。SpringFramework支持五種作用域(其中有三種只能用在基于web的SpringApplicationContext)。內(nèi)置支持的作用域分列如下頁圖表說明: 示例ject演示prototype作用域 Bean作用域bean的作用域-初始化web配置
要使用request、session和globalsession作用域的bean(即具有web作用域的bean),在開始設(shè)置bean定義之前,還要做少量的初始配置。請注意,假如你只想要“常規(guī)的”作用域,也就是singleton和prototype,就不需要這一額外的設(shè)置。在目前的情況下,根據(jù)你的特定servlet環(huán)境,有多種方法來完成這一初始設(shè)置。如果你使用的是Servlet2.4及以上的web容器,那么你僅需要在web應(yīng)用的XML聲明文件web.xml中增加下述ContextListener即可:bean的作用域-初始化web配置
<web-app> ...<listener><listener-class> org.springframework.web.context.request.
RequestContextListener</listener-class></listener> ...</web-app>Request作用域 考慮下面bean定義:
<beanid="loginAction"class="com.foo.LoginAction" scope="request"/>
針對每次HTTP請求,Spring容器會根據(jù)loginActionbean定義創(chuàng)建一個全新的LoginActionbean實例,且該loginActionbean實例僅在當前HTTPrequest內(nèi)有效,因此可以根據(jù)需要放心的更改所建實例的內(nèi)部狀態(tài),而其他請求中根據(jù)loginActionbean定義創(chuàng)建的實例,將不會看到這些特定于某個請求的狀態(tài)變化。當處理請求結(jié)束,request作用域的bean實例將被銷毀。bean的作用域-初始化web配置Session作用域 考慮下面bean定義:
<beanid="userPreferences"class="com.foo.UserPreferences" scope="session"/>
針對某個HTTPSession,Spring容器會根據(jù)userPreferencesbean定義創(chuàng)建一個全新的userPreferencesbean實例,且該userPreferencesbean僅在當前HTTPSession內(nèi)有效。與request作用域一樣,你可以根據(jù)需要放心的更改所創(chuàng)建實例的內(nèi)部狀態(tài),而別的HTTPSession中根據(jù)userPreferences創(chuàng)建的實例,將不會看到這些特定于某個HTTPSession的狀態(tài)變化。當HTTPSession最終被廢棄的時候,在該HTTPSession作用域內(nèi)的bean也會被廢棄掉。bean的作用域-初始化web配置bean定義的繼承
在bean定義中包含了大量的配置信息,其中包括容器相關(guān)的信息(比如初始化方法、靜態(tài)工廠方法名等等)以及構(gòu)造器參數(shù)和屬性值。子bean定義就是從父bean定義繼承配置數(shù)據(jù)的bean定義。它可以覆蓋父bean的一些值,或者添加一些它需要的值。使用父/子bean定義的形式可以節(jié)省很多的輸入工作。實際上,這就是一種模板形式。當以編程的方式使用BeanFactory時,子bean定義用ChildBeanDefinition類表示。大多數(shù)用戶從來不需要以這個方式使用它們,而是以類似XmlBeanFactory中的聲明方式去配置bean定義。當使用基于XML的配置元數(shù)據(jù)時,給‘parent’屬性指定值,意味著子bean定義的聲明。見下頁代碼示例: <beanid="inheritedTestBean"abstract="true" class="org.springframework.beans.TestBean"> <propertyname="name"value="parent"/> <propertyname="age"value="1"/> </bean> <beanid="inheritsWithDifferentClass" class="org.springframework.beans.DerivedTestBean" parent="inheritedTestBean"init-method="initialize"> <propertyname="name"value="override"/>
<!--theagepropertyvalueof1willbeinheritedfromparent--></bean>詳細見示例:spring-injectionVject spring-autowireByType/Njectbean定義的繼承ApplicationContext接口beans包提供了以編程的方式管理和操控bean的基本功能,而context包下的ApplicationContext以一種更加面向框架的方式增強了BeanFactory的功能。多數(shù)用戶可以采用聲明的方式來使用ApplicationContext,甚至不用手動創(chuàng)建它,而通過ContextLoader這樣的支持類,把它作為J2EEweb應(yīng)用的一部分自動啟動。當然,我們?nèi)匀豢梢圆捎镁幊痰姆绞絼?chuàng)建一個ApplicationContext。context包的核心是ApplicationContext接口。它由BeanFactory接口派生而來,因而提供了BeanFactory所有的功能。為了以一種更向面向框架的方式工作以及對上下文進行分層和實現(xiàn)繼承,context包還提供了以下的功能:MessageSource,提供國際化的消息訪問資源訪問,如URL和文件事件傳播,實現(xiàn)了ApplicationListener接口的bean載入多個(有繼承關(guān)系)上下文,使得每一個上下文都專注于一個特定的層次,比如應(yīng)用的web層由于ApplicationContext包括了BeanFactory所有的功能,所以通常建議優(yōu)先采用ApplicationContext。接下來將敘述由ApplicationContext在BeanFactory的基礎(chǔ)上所添加的那些功能。底層資源的訪問:為了更好的使用和理解應(yīng)用上下文,通常用戶應(yīng)當對Spring的Resource有所了解。應(yīng)用上下文同時也是個資源加載器(ResourceLoader),能被用來加載多個Resource。一個Resource實質(zhì)上可以當成一個.URL,可被用來從大多數(shù)位置上以透明的方式獲取底層的資源,包括從classpath、文件系統(tǒng)位置、任何以標準URL描述的位置以及其它一些變種。ApplicationContext構(gòu)造器的路徑就是實際的資源串,根據(jù)不同的上下文實現(xiàn),字符串可視為不同的形式(例如:ClassPathXmlApplicationContext會把路徑字符串看作一個classpath路徑)。然而,它也可以使用特定的前綴來強制地從classpath或URL加載bean定義文件,而不管實際的上下文類型。ApplicationContext接口-
由ApplicationContext在BeanFactory的基礎(chǔ)上所添加的功能
與BeanFactory通常以編程的方式被創(chuàng)建不同的是,ApplicationContext能以聲明的方式創(chuàng)建,如使用ContextLoader。 當然你也可以使用ApplicationContext的實現(xiàn)之一來以編程的方式創(chuàng)建ApplicationContext實例。首先,讓我們先分析ContextLoader接口及其實現(xiàn)。ContextLoader接口有兩個實現(xiàn): ContextLoaderListener和ContextLoaderServlet。兩者都實現(xiàn)同樣的功能,但不同的是,ContextLoaderListener不能在與Servlet2.2兼容的web容器中使用。根據(jù)Servlet2.4規(guī)范,servletcontextlistener要在web應(yīng)用程序的servletcontext建立后立即執(zhí)行,并要能夠響應(yīng)第一個請求(在servletcontext要關(guān)閉時也一樣):這樣一個servletcontextlistener是初始化SpringApplicationContext的理想場所。ApplicationContext接口-
ApplicationContext在WEB應(yīng)用中的實例化
你可以象下面那樣使用ContextLoaderListener來注冊一個ApplicationContext:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>
/WEB-INF/daoContext.xml/WEB-INF/applicationContext.xml </param-value> </context-param>ApplicationContext接口 <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener><!--orusetheContextLoaderServletinsteadoftheabovelistener <servlet> <servlet-name> context </servlet-name> <servlet-class> org.springframework.web.context.ContextLoaderServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> -->
ApplicationContext接口構(gòu)造application
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 新版華東師大版八年級數(shù)學下冊《16.1.2分式的基本性質(zhì)通分》聽評課記錄3
- 五年級數(shù)學下冊聽評課記錄《3.1 分數(shù)乘法(一)》(3)-北師大版
- 2025年自返式取樣器合作協(xié)議書
- 蘇科版七年級數(shù)學上冊《2.6.2有理數(shù)的乘法與除法》聽評課記錄
- 小學二年級數(shù)學口算題大全
- 七年級上冊歷史第10課《秦末農(nóng)民大起義》聽課評課記錄
- 五年級下冊口算練習
- 人教版數(shù)學八年級下冊《一次函數(shù)的概念》聽評課記錄1
- 白酒銷售工作計劃書范本
- 聚合支付渠道服務(wù)協(xié)議書范本
- 2025年汽車加氣站作業(yè)人員安全全國考試題庫(含答案)
- 化工過程安全管理導則安全儀表管理課件
- 高三日語一輪復習日語助詞「に」和「を」的全部用法課件
- 【化學】高中化學手寫筆記
- 中國高血壓防治指南-解讀全篇
- 2024年監(jiān)控安裝合同范文6篇
- 2024年山東省高考政治試卷真題(含答案逐題解析)
- 煙葉復烤能源管理
- 食品安全管理員考試題庫298題(含標準答案)
- 執(zhí)業(yè)醫(yī)師資格考試《臨床執(zhí)業(yè)醫(yī)師》 考前 押題試卷絕密1 答案
- 非ST段抬高型急性冠脈綜合征診斷和治療指南(2024)解讀
評論
0/150
提交評論