第19章spring的ioc_第1頁
已閱讀1頁,還剩36頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、第19章 Spring的IoC,本章將詳細深入地探討Spring框架的控制反轉(zhuǎn)實現(xiàn)(Inversion of Control,IoC)原理。Spring框架所提供的眾多功能之所以能成為一個整體,正是創(chuàng)建在IoC的基礎(chǔ)之上,因此對這一內(nèi)涵簡單、外延豐富的技術(shù)有必要進行詳細的介紹。,19.1 Bean工廠,org.springframework.beans.factory.BeanFactory是Spring IoC容器的實際代表者,I

2、oC容器負責(zé)容納此前所描述的bean,并對bean進行管理。如圖所示,Spring中IoC容器就是對象的加工廠,可以按照元數(shù)據(jù)填充和組裝Java對象。,19.1.1 創(chuàng)建Bean工廠,在Spring中,BeanFactory是IoC容器的核心接口。它的職責(zé)包括:實例化、定位、配置應(yīng)用程序中的對象及創(chuàng)建這些對象間的依賴。從本質(zhì)上講,BeanFactory僅僅只是一個維護bean定義以及相互依賴關(guān)系的高級工廠接口。通過BeanFacto

3、ry可以訪問bean定義。Spring提供了許多易用的BeanFactory實現(xiàn),XmlBeanFactory就是最常用的一個。該實現(xiàn)將以XML方式描述組成應(yīng)用的對象以及對象間的依賴關(guān)系。XmlBeanFactory類將持有此XML配置元數(shù)據(jù),并用它來構(gòu)建一個完全可配置的系統(tǒng)或應(yīng)用。,19.1.2 使用多個文件,將XML配置文件分拆成多個部分是非常有用的。為了加載多個XML文件生成一個ApplicationContext實例,可以將文

4、件路徑作為字符串數(shù)組傳給ApplicationContext構(gòu)造函數(shù)。而bean factory將通過調(diào)用bean defintion reader從多個文件中讀取bean定義。通常情況下,Spring團隊傾向于上述做法,因為這樣各個配置并不會查覺到它們與其他配置文件的組合。另外一種方法是使用一個或多個的元素來從另外一個或多個文件加載bean定義。,19.1.3 獲取Bean,就Spring IoC容器而言,bean定義基本上描述了

5、創(chuàng)建一個或多個實際bean對象的內(nèi)容。當需要的時候,容器會從bean定義列表中取得一個指定的bean定義,并根據(jù)bean定義里面的配置元數(shù)據(jù)使用反射機制來創(chuàng)建一個實際的對象。當使用基于XML的元數(shù)據(jù)配置文件,可以這樣來指定bean類:,19.1.4 BeanFactory的其它方法,除了getBean()方法可以取得bean的實例;BeanFactory還提供其他的方法供客戶代碼調(diào)用:boolean containsBean(

6、String):如果BeanFactory包含給定名稱的bean定義(或bean實例),則返回true。Object getBean(String):返回以給定名字注冊的bean實例。根據(jù)bean的配置情況,如果為singleton模式將返回一個共享的實例,否則將返回一個新建的實例。如果沒有找到指定的bean,該方法可能會拋出BeansException異常(實際上將拋出NoSuchBeanDefinitionException異常)

7、,在對bean進行實例化和預(yù)處理時也可能拋出異常,19.1.4 BeanFactory的其它方法,Object getBean(String, Class):返回以給定名稱注冊的bean實例,并轉(zhuǎn)換為給定class類型的實例,如果轉(zhuǎn)換失敗,相應(yīng)的異常(BeanNotOfRequiredTypeException)將被拋出。上面的getBean(String)方法也適用該規(guī)則。Class getType(String name):返回

8、給定名稱的bean的Class。如果沒有找到指定的bean實例,則拋出NoSuchBeanDefinitionException異常。boolean isSingleton(String):判斷給定名稱的bean定義(或bean實例)是否為singleton模式(singleton將在bean的作用域中討論),如果bean沒找到,則拋出NoSuchBeanDefinitionException異常。String[] getAlias

9、es(String):返回給定bean名稱的所有別名。,19.2 配置Bean,在Spring中,那些組成應(yīng)用的主體(backbone)及由Spring IoC容器所管理的對象被稱之為bean。簡單地講,bean就是由Spring容器初始化、裝配及被管理的對象,除此之外,bean就沒有特別之處了(與應(yīng)用中的其他對象沒有什么區(qū)別)。而bean定義以及bean相互間的依賴關(guān)系將通過配置元數(shù)據(jù)來描述。,19.2.1 bean的定義,Spr

10、ing IoC容器將管理一個或多個bean,這些bean將通過配置文件中的bean定義被創(chuàng)建(在XML格式中為元素)。在容器內(nèi)部,這些bean定義由BeanDefinition 對象來表示,該定義將包含以下信息:全限定類名:這通常就是已定義bean的實際實現(xiàn)類。如果通過調(diào)用static factory方法來實例化bean,而不是使用常規(guī)的構(gòu)造函數(shù),那么類名稱實際上就是工廠類的類名。bean行為的定義,即創(chuàng)建模式(prototype還

11、是singleton)、自動裝配模式、依賴檢查模式、初始化以及銷毀方法。這些定義將決定bean在容器中的行為用于創(chuàng)建bean實例的構(gòu)造函數(shù)參數(shù)及屬性值。比如使用bean來定義連接池,可以通過屬性或者構(gòu)造參數(shù)指定連接數(shù),以及連接池大小限制等。bean之間的關(guān)系,即協(xié)作(或者稱依賴)。,19.2.2 bean命名約定,bean的命名采用標準的Java命名約定,即小寫字母開頭,首字母大寫間隔的命名方式。如accountManager、ac

12、countService、userDao及l(fā)oginController,等等。對bean采用統(tǒng)一的命名約定將會使配置更加簡單易懂。而且在使用Spring AOP時,如果要發(fā)通知(advice)給與一組名稱相關(guān)的bean時,這種簡單的命名方式將會帶來額外的好處,如可以使用統(tǒng)配符來一次配置多個bean。每個bean都有一個或多個id(或稱之為標識符或名稱,在術(shù)語上可以理解成一回事)。這些id在當前IoC容器中必須唯一。如果一個bean

13、有多個id,那么其他的id在本質(zhì)上將被認為是別名。,19.2.3 bean的別名,在對bean進行定義時,除了使用id屬性來指定名稱之外,為了提供多個名稱,需要通過alias屬性來加以指定。而所有的這些名稱都指向同一個bean,在某些情況下提供別名非常有用,比如為了讓應(yīng)用的每一個組件能更容易的對公共組件進行引用。然而,在定義bean時就指定所有的別名并不是總是恰當?shù)?。有時期望能在當前位置為那些在別處定義的bean引入別名。在XML配

14、置文件中,可用單獨的元素來完成bean別名的定義。如:,19.3 依賴,依賴注入(Dependency Injection簡稱DI)背后的基本原理是對象之間的依賴關(guān)系(即一起工作的其它對象)只會通過以下幾種方式來實現(xiàn):構(gòu)造函數(shù)的參數(shù)、工廠方法的參數(shù),或給由構(gòu)造函數(shù)或者工廠方法創(chuàng)建的對象設(shè)置屬性。因此,容器的工作就是創(chuàng)建bean時注入那些依賴關(guān)系。相對于由bean自己來控制其實例化、直接在構(gòu)造函數(shù)中指定依賴關(guān)系或則類似服務(wù)定位器(Se

15、rvice Locator)模式這3種自主控制依賴關(guān)系注入的方法來說,控制從根本上發(fā)生了倒轉(zhuǎn),這也正是控制反轉(zhuǎn)(Inversion of Control,IoC)名字的由來。,19.3.1 Setter注入,通過調(diào)用無參構(gòu)造函數(shù)或無參static工廠方法實例化bean之后,調(diào)用該bean的setter方法,即可實現(xiàn)基于屬性的set()方法(又被稱為setter)的DI。下面的例子將展示使用setter注入依賴。注意,這個類并沒有什么

16、特別之處,它就是普通的Java類,,19.3.2 構(gòu)造函數(shù)注入,Spring推薦使用Setter injection,也就是Setter 注入,但也允許使用構(gòu)造函數(shù)來注入(Constructor injection),使用Setter或Constructor來注入依賴關(guān)系應(yīng)該視需求而定。.在Bean的定義文件中,使用來表示將使用Constructor injection,由于使用Constructor injection時并不如Se

17、tter injection時擁有setXXX()這樣易懂的名稱,所以必須指定參數(shù)的位置索引,index屬性就是用于指定實例將注入至構(gòu)造函數(shù)中的哪一個參數(shù),參數(shù)的順序指定中,第一個參數(shù)的索引值是0,第二個是1,依此類推。,19.3.3 引用其它的bean(協(xié)作者),在前兩節(jié)中介紹的或元素內(nèi)部還可以使用ref元素。該元素用來將bean中指定屬性的值設(shè)置為對容器中的另外一個bean的引用。如前所述,該引用bean將被作為依賴注入,而且在注

18、入之前會被初始化(如果是singleton bean則已被容器初始化)。盡管都是對另外一個對象的引用,但是通過id/name指向另外一個對象卻有三種不同的形式,不同的形式將決定如何處理作用域及驗證。,19.3.4 使用depends-on,多數(shù)情況下,一個bean對另一個bean的依賴最簡單的做法就是將一個bean設(shè)置為另外一個bean的屬性。在xml配置文件中最常見的就是使用元素。有時候它還有另外一種變體,如果一個bean能感知Io

19、C容器,只要給出它所依賴的id,那么就可以通過編程的方式從容器中取得它所依賴的對象。無論采用哪一種方法,被依賴bean將在依賴bean之前被適當?shù)某跏蓟T谏贁?shù)情況下,有時候bean之間的依賴關(guān)系并不是那么的直接(例如,當類中的靜態(tài)塊的初始化被時,如數(shù)據(jù)庫驅(qū)動的注冊)。,19.3.5 注入集合類,對于像陣列、java.util.List、java.util.Set、java.util.Map等集合實例,在注入前必須填充入一些實例至集

20、合中,然后再將集合實例注入至所需的Bean中,在foobean的accounts屬性被注入之前,通過反射,利用強類型Map的泛型信息,Spring的底層類型轉(zhuǎn)換機制將會把各種value元素值轉(zhuǎn)換為Float類型,因此字符串9.99、2.75及3.99就會被轉(zhuǎn)換為實際的Float類型。,19.3.6 自動裝配,BeanFactory能夠自動裝配合作bean之間的關(guān)系。這就意味著,讓Spring通過檢查BeanFactory的內(nèi)容來自動

21、裝配bean的合作者(其他的bean),這是有可能的。自動裝配功能有5種模式。通過使用自動裝配,可以減少(或消除)指定屬性(或構(gòu)造函數(shù)參數(shù))的,使配置文件更加簡潔容易理解,更能減少因為手工輸入帶來的錯誤。在XmlBeanFactory中,使用bean元素的autowire屬性來指定bean定義的自動裝配模式。,19.4 Bean的特性,Spring對Bean沒有任何特殊要求,需要實現(xiàn)特殊接口。但它卻比普通的Java Bean多了很多

22、特性。并且使用者不但可以通過IoC容器獲得這些Bean,還可以通過程序來控制它們在容器中實例化的行為。,19.4.1 Bean的作用域,在創(chuàng)建一個bean定義(通常為XML配置文件)時,可以簡單的將其理解為:用以創(chuàng)建由該bean定義所決定的實際對象實例的一張“處方(recipe)”或者模板。就如class一樣,根據(jù)一張“處方”可以創(chuàng)建多個對象實例。不僅可以控制注入到對象(bean定義)中的各種依賴和配置值,還可以控制該對象的作用域。

23、這樣可以靈活選擇所建對象的作用域,而不必在Java Class級定義作用域。Spring Framework支持五種作用域(其中有三種只能用在基于web的Spring ApplicationContext)。,19.4.2 改變Bean的行為,Spring提供了幾個標志接口(marker interface),這些接口用來改變?nèi)萜髦衎ean的行為(1)初始化回調(diào)(2)析構(gòu)回調(diào)(3)獲取反向獲取BeanFactory(4)Bea

24、nNameAware,19.4.3 Bean的生命周期,在傳統(tǒng)的Java應(yīng)用中,Bean的聲明周期非常簡單。Java的關(guān)鍵詞new用來實例化Bean,這樣就夠用了。那么在Spring中Bean產(chǎn)生是由Spring的IoC容器控制的。它們的生命周期也與Spring的IoC容器有關(guān)??偨Y(jié)前幾節(jié)的內(nèi)容不難得出一個Bean在Spring中的生命周期。如圖,當一個典型的Bean被載入的BeanFactory容器時,它的生命周期也就開始了。,1

25、9.5 利用ApplicationContext,beans包提供了以編程的方式管理和操控bean的基本功能,而context包下的ApplicationContext以一種更加面向框架的方式增強了BeanFactory的功能。多數(shù)用戶可以采用聲明的方式來使用ApplicationContext,甚至不用手動創(chuàng)建它,而通過ContextLoader這樣的支持類,把它作為J2EE web應(yīng)用的一部分自動啟動。當然仍然可以采用編程的方式創(chuàng)

26、建一個ApplicationContext。context包的核心是ApplicationContext接口。它由BeanFactory接口派生而來,因而提供了BeanFactory所有的功能。,19.5.1 利用MessageSource實現(xiàn)國際化,ApplicationContext接口擴展了MessageSource接口,因而提供了消息處理的功能(i18n或者國際化)。與HierarchicalMessageSource一起使

27、用,它還能夠處理嵌套的消息,這些是Spring提供的處理消息的基本接口??焖贋g覽一下它所定義的方法:String getMessage(String code, Object[] args, String default, Locale loc):用來從MessageSource獲取消息的基本方法。String getMessage(String code, Object[] args, Locale loc):本質(zhì)上和上一個方法相

28、同,其區(qū)別在:沒有指定默認值,如果沒找到消息,會拋出一個NoSuchMessageException異常。String getMessage(MessageSourceResolvable resolvable, Locale locale):上面方法中所使用的屬性都封裝到一個MessageSourceResolvable實現(xiàn)中,而本方法可以指定MessageSourceResolvable實現(xiàn)。,19.5.2 事件處理,Appli

29、cationContext中的事件處理是通過ApplicationEvent類和ApplicationListener接口來提供的。如果在上下文中部署一個實現(xiàn)了ApplicationListener接口的bean,那么每當一個ApplicationEvent發(fā)布到ApplicationContext時,這個bean就得到通知。實質(zhì)上,這是標準的Observer設(shè)計模式。Spring提供了三個標準事件:同樣也可以實現(xiàn)自定義的事件。僅僅是

30、簡單地調(diào)用ApplicationContext的publishEvent()方法,且指定一個實現(xiàn)了ApplicationEvent的自定義事件類實例做參數(shù)。事件監(jiān)聽器同步地接收消息,這意味著publishEvent()會被加鎖直到所有的監(jiān)聽者都處理完事件(也可以通過ApplicationEventMulticaster實現(xiàn)來使用其它的事件發(fā)送策略)。此外,如果使用一個事務(wù)上下文,一個監(jiān)聽者接收事件時會在發(fā)送者的事務(wù)上下文中操作事件。,1

31、9.5.3 底層資源的訪問,為了更好的使用和理解應(yīng)用上下文,通常用戶應(yīng)當對Spring的Resource有所了解。應(yīng)用上下文同時也是個資源加載器(ResourceLoader),能被用來加載多個Resource。一個Resource實質(zhì)上可以當成一個java.net.URL,可被用來從大多數(shù)位置以透明的方式獲取底層的資源,包括從classpath、文件系統(tǒng)位置、任何以標準URL描述的位置以及其它一些變種。如果資源位置串是一個沒有任何前

32、綴的簡單路徑,這些資源來自何處取決于實際應(yīng)用上下文的類型。部署在應(yīng)用上下文的bean可能會實現(xiàn)一個特殊的標志接口ResourceLoaderAware,它會在初始化時自動回調(diào)將應(yīng)用上下文本身作為資源加載器傳入。,19.5.4 延遲初始化bean,ApplicationContext實現(xiàn)的默認行為就是在啟動時將所有singleton bean提前進行實例化。提前實例化意味著作為初始化過程的一部分,ApplicationContext實

33、例會創(chuàng)建并配置所有的singleton bean。通常情況下這是件好事,因為這樣在配置中的任何錯誤就會即刻被發(fā)現(xiàn)。有時候這種默認處理可能并不是用戶想要的。如果不想讓一個singleton bean在ApplicationContext實現(xiàn)在初始化時被提前實例化,那么可以將bean設(shè)置為延遲實例化。一個延遲初始化bean將告訴IoC 容器是在啟動時還是在第一次被用到時實例化。,19.5.5 ApplicationContext在WEB

34、應(yīng)用中的實例化,與BeanFactory通常以編程的方式被創(chuàng)建不同的是,ApplicationContext能以聲明的方式創(chuàng)建,如使用ContextLoader。當然也可以使用ApplicationContext的實現(xiàn)之一來以編程的方式創(chuàng)建ApplicationContext實例。首先,先分析ContextLoader接口及其實現(xiàn)。ContextLoader接口有兩個實現(xiàn):ContextLoaderListener和ContextLo

35、aderServlet。兩者都實現(xiàn)同樣的功能,但不同的是,ContextLoaderListener不能在與Servlet 2.2兼容的web容器中使用。,19.6 使用注釋定義IoC(2.5新增),基于注釋(Annotation)的配置有越來越流行的趨勢,Spring 2.5順應(yīng)這種趨勢,提供了完全基于注釋配置 Bean、裝配 Bean 的功能,您可以使用基于注釋的 Spring IoC 替換原來基于XML的配置。本節(jié)將以一個例子來

36、說明如何用注釋來定義IoC。,19.6.1 用例介紹,在本例中有3個類,它們分別是 Office、Car 和 Boss,這3個類需要在Spring容器中配置為Bean,其中Office和Car是Boss的兩個屬性。那么在傳統(tǒng)的IoC中應(yīng)該使用元素注入兩個屬性到Boss,,19.6.2 使用@Autowired注釋,Spring 2.5引入了@Autowired注釋,它可以對類成員變量、方法及構(gòu)造函數(shù)進行標注,完成自動裝配的工作。來看

37、一下使用@Autowired進行成員變量自動注入的代碼,這樣,當Spring容器啟動時,AutowiredAnnotationBeanPostProcessor將掃描 Spring 容器中所有Bean,當發(fā)現(xiàn)Bean中擁有@Autowired 注釋時就找到和其匹配(默認按類型匹配)的Bean,并注入到對應(yīng)的地方中去。技巧:按照上面的配置,Spring將直接采用Java反射機制對Boss中的car和office 這兩個私有成員變量進行

38、自動注入。所以對成員變量使用@Autowired后,甚至可以將sette 方法(setCar()和setOffice())從Boss中刪除。,19.6.3 在Setter方法上使用注釋,上例中@Autowired注釋標注在了屬性上,也可以把它使用在Setter方法上這時,@Autowired 將查找被標注的方法的入?yún)㈩愋偷?Bean,并調(diào)用方法自動注入這些 Bean。而下面的使用方法則對構(gòu)造函數(shù)進行標注:,19.6.4 在構(gòu)造函數(shù)

39、中使用注釋,同樣也可以通過@Autowired對方法或構(gòu)造函數(shù)進行標注,這時,@Autowired 將查找被標注的方法的入?yún)㈩愋偷腂ean,并調(diào)用方法自動注入這些Bean。而下面的使用方法則對構(gòu)造函數(shù)進行標注。由于Boss()構(gòu)造函數(shù)有兩個入?yún)?,分別是car和office,@Autowired將分別尋找和它們類型匹配的Bean,將它們作為Boss(Car car,Office office)的入?yún)韯?chuàng)建Boss Bean。,19.6.

40、5 處理出現(xiàn)多個匹配情況,在默認情況下使用@Autowired 注釋進行自動注入時,Spring 容器中匹配的候選Bean數(shù)目必須有且僅有一個。當找不到一個匹配的Bean時,Spring容器將拋出 BeanCreationException異常,并指出必須至少擁有一個匹配的 Bean。當不能確定Spring容器中一定擁有某個類的Bean時,可以在需要自動注入該類Bean的地方可以使用@Autowired(required = fal

41、se),這等于告訴 Spring:在找不到匹配 Bean 時也不報錯,19.6.6 使用JSR-250的注釋,Spring 不但支持自己定義的@Autowired 的注釋,還支持幾個由 JSR-250 規(guī)范定義的注釋,它們分別是@Resource、@PostConstruct 以及@PreDestroy。(1)@Resource 的作用相當于@Autowired,只不過@Autowired按byType自動注入,面@Resource

42、 默認按 byName 自動注入罷了。(2)Spring 容器中的 Bean 是有生命周期的,Spring允許在Bean在初始化完成后以及 Bean 銷毀前執(zhí)行特定的操作,您既可以通過實現(xiàn)InitializingBean/DisposableBean接口來定制初始化之后/銷毀之前的操作方法,也可以通過元素的 init-method/destroy-method 屬性指定初始化之后 / 銷毀之前調(diào)用的操作方法。,19.6.7 徹底擺脫

43、配置文件,雖然可以通過@Autowired或@Resource在Bean類中使用自動注入功能,但是Bean還是在XML文件中通過進行定義——也就是說,在XML配置文件中定義Bean,通過@Autowired或@Resource為Bean的成員變量、方法入?yún)⒒驑?gòu)造函數(shù)入?yún)⑻峁┳詣幼⑷氲墓δ?。能否也通過注釋定義Bean,從XML配置文件中完全移除Bean定義的配置呢?答案是肯定的,通過Spring 2.5提供的@Component 注釋就可

44、以達到這個目標了。,19.7 小結(jié),本章詳細介紹了Spring中IoC容器的原理和使用方法,用幾個例子說明了如何用Spring的IoC來解決實際問題,主要就是如何配置Spring中的Bean。處理基本的BeanFactory又介紹了一個很使用的工具類ApplicationContext通過它可以實現(xiàn)很多實用的功能,如國際化、底層資源。最后還介紹了Spring2.5帶來的最新功能,使用注釋來實現(xiàn)IoC配置。IoC是Spring的基礎(chǔ),

溫馨提示

  • 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. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論