Spring技術(shù)手冊筆記(一):入門、Bean、消息、事件
Posted on 2009-11-06 18:43 codingliyi 閱讀(721) 評論(0) 編輯 收藏 所屬分類: Java EESpring的核心是個lightweitht 的container,他是實現(xiàn)IOC容器、非侵入性(No Intrusive)的框架,并提供AOP概念的實現(xiàn)方式,提供Persistence、transaction的支持,提供MVC Web框架的實現(xiàn),并對一些常用的企業(yè)服務(wù)API提供一致的模型封裝,是一個全方位的Application Framework。
一、Spring部分術(shù)語介紹
No Intrusive:應(yīng)用程序幾乎感覺不到框架的存在,減低應(yīng)用程序在框架移植時的負擔(dān),進一步增加應(yīng)用程序組件的Reusability。
控制反轉(zhuǎn)(IoC):依賴關(guān)系的轉(zhuǎn)移。程序不應(yīng)依賴實現(xiàn),而是依賴于接口。
即如果A依賴B,則B擁有控制權(quán)。依賴關(guān)系的反轉(zhuǎn)即是控制關(guān)系的反轉(zhuǎn),將控制權(quán)由實現(xiàn)的一方轉(zhuǎn)移至抽象的一方,藉由讓抽象方擁有控制權(quán),可以獲得組件的殼重用性。
在例子中,整個控制權(quán)從實際的FloppyWriter轉(zhuǎn)移到抽象的IDeviceWriter接口上m而讓Business依賴于IDeviceWriter接口,而FloppyWriter和UsbDiskWriter也依賴于IDeviceWriter接口。
依賴注入(Dependency Injection):IoC模式是一個高層的模式概念,實現(xiàn)IoC有兩種方式:Dependency Injection和Service Locator,Spring采用的是DI。
保留抽象接口,讓組件依賴于抽象接口,當(dāng)組件要與其他實際的對象發(fā)生依賴關(guān)系時,通過抽象接口來注入依賴的實際對象。
依賴注入的三種實現(xiàn)方式:Interface Injection、Setter Injection、Constructor Injection。
二、第一個Spring程序。
載入配置文件:

2

ClassPathResource:從系統(tǒng)的類路徑中加載,在上述的代碼中,目錄的層次結(jié)構(gòu)如下圖所示:

FileSystemResource:從文件系統(tǒng)加載,比如說自己指定配置文件的全路徑
InputStreamResource:從輸入流中加載
ServletContextResource:從Servlet 上下文環(huán)境中加載
UrlResource:從指定的Url加載
一、Bean、消息、事件
1. BeanFactory、ApplicationContext
BeanFactory負責(zé)讀取Bean定義文件,管理對象的加載、生成,維護Bean對象與Bean對象之間的依賴關(guān)系,負責(zé)Bean的生命周期。
ApplicationContext具備如BeanFactory基本的容器管理功能之外,還提供一個應(yīng)用程序所需的更完整的框架功能,如取得資源文件的更方便的方法,提供文字消息解析的方法,支持國際化消息,事件的發(fā)布、處理與傳播等。
建議用ApplicationContext替代BeanFactory。在實現(xiàn)ApplicationContext的類中,最常用的是以下三個:
org.springframework.context.support.FileSystemXmlApplicationContext:可指定XML定義文件的相對路徑或者絕對路徑來讀取定義文件。
org.springframework.context.support.ClassPathXmlApplicationContext:從Classpath設(shè)定路徑中來讀取XML定義文件。
2. 使用Constructor Injection
即使使用Constructor Injection,也建議定義一個無參構(gòu)造方法,以讓Spring可以有使用無參構(gòu)造方法來生成對象的彈性。
在Bean定義文件中,必須指定構(gòu)造方法上參數(shù)的順序,如下




建議使用Setter構(gòu)造方法。有時需要隱藏某屬性的Setter方法時(如使該屬性變?yōu)橹蛔x或私有),可使用Constructor Injection。
3. 屬性綁定
如某個Bean實例只被某個屬性參考一次,之那么可以在屬性定義時使用Bean標簽,并僅需指定其class屬性即可。如

2

3

Spring也支持隱式的自動綁定。

若使用byType無法完成綁定,則拋出異常;
若使用byName無法完成綁定,則對應(yīng)得Setter僅維持未綁定狀態(tài);
若使用constructor,Spring容器會試圖比較對應(yīng)容器中的Bean實例類型,及相關(guān)構(gòu)造方法上的參數(shù)類型;
若使用autodetect,Spring首先嘗試constructor,不行的話再嘗試byType。
dependency-check指定依賴檢查的方式,默認為none。如進行依賴檢查時發(fā)現(xiàn)有未完成的伊拉關(guān)系,則執(zhí)行時會跑出異常。
4. 集合類屬性的注入。



















5. Bean的生命周期
使用BeanFactory來生成及管理Bean實例時:
Bean的建立:讀取Bean定義文件,生成Bean的實例。
屬性注入:執(zhí)行相關(guān)Bean屬性的依賴注入。
BeanNameAware的setBeanName():
如Bean實現(xiàn)了BeanNameAware接口,則執(zhí)行。
BeanFactoryAware的setBeanFactory():
如Bean實現(xiàn)了BeanFactoryAware接口,則執(zhí)行。
BeanPostProcessors的processBeforeInitialization():
如任何BeanPostProcessors實例與Bean實例關(guān)聯(lián),則執(zhí)行。
InitializingBean的afterPropertiesSet()
如Bean實現(xiàn)了InitializingBean接口,則執(zhí)行。
Bean定義文件中定義的init-method
如定義了init-method,則執(zhí)行設(shè)定的方法名稱。
BeanPostProcessors的processAfterInitialization():
如任何BeanPostProcessors實例與Bean實例關(guān)聯(lián),則執(zhí)行。
DisposableBean的destory()
如Bean實現(xiàn)了DisposableBean接口,則執(zhí)行。
Bean定義文件中定義的destory-method
如定義了destory-method,則執(zhí)行設(shè)定的方法名稱。
若使用ApplicationContext,在執(zhí)行setBeanFactory()后,若bean有實現(xiàn)ApplicationContextAware接口,則執(zhí)行setApplicationContext(),接著再繼續(xù)執(zhí)行之后的流程。
6. Bean高級管理
Aware接口
有時為了善用Spring所提供的一些功能,必須讓Bean知道Spring容器管理的一些細節(jié),或者讓它知道BeanFactory,ApplicationContext的存在。
Spring中提供了一些Aware接口。如BeanNameAware,BeanFactoryAware,ApplicationContextAware。
當(dāng)Bean實現(xiàn)了上述接口后,在依賴關(guān)系設(shè)定完成之后,初始化方法之前,Spring容器會注入對應(yīng)的實例。
(在暑期實習(xí)中做的那個Flex項目,需要在Action層使用ApplicationContext得到服務(wù)層組件。當(dāng)時使用的是直接在代碼中用new創(chuàng)建。其實現(xiàn)在看來可以實現(xiàn)ApplicationContextAware接口)
BeanPostProcessor接口

2

3

4

5

6

例如將注入的String改為大寫,代碼如下:

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

7. 資源、消息、事件
ApplicationContext除了具備如BeanFactory基本的容器管理功能之外,并支持更多應(yīng)用框架的特性,像是資源的取得、消息解析、事件的處理與傳播。
資源的取得:ApplicationContext繼承了ResourceLoader接口,可使用getResource()方法并指定資源文件的URL來取得一個實現(xiàn)Resource接口的實例。
Resource resource = context.getResource("classpath:admin.properties");
也可以指定其他標準的URL,如file:或http:等。
在Spring應(yīng)用程序執(zhí)行期間,ApplicationContext本身就會發(fā)布一連串的事件,而所有發(fā)布的時間都是抽象類ApplicationEvent的子類。
ApplicationContext會在ApplicationEvent發(fā)布時通知實現(xiàn)了ApplicationListener的Bean類實例。
如果打算發(fā)布事件通知ApplicationListener的實例,則可使用ApplicationContext的publishEvent()方法。