beans包提供了以編程方式管理和操作bean的基本功能而context包增加了ApplicationContext它以一種更加面向框架的方式增強了BeanFactory的功能
context包的基礎是位於orgntext包中的ApplicationContext接口它是由BeanFactory接口派生而來的提供了BeanFactory的所有功能為了以一種更面向框架的方式工作使用分層和繼承關系的上下文context包還提供了一下的功能
a MessageSource對IN消息的訪問
b 資源訪問例如URL和文件
c 事件傳遞給是吸納了ApplicationListener接口的bean
d 載入多個(有繼承關系)上下文使得每一個上下文都專注於一個特定的層是比如應用的web層
國際化支持
ApplicationContext擴展了MessageSource接口因而提供了messaging的功能(IN或者國際化)同NestingMessageSource一起使用還能處理分級的信息這些是spring提供的處理信息的基本接口
當一個ApplicationContext被加載時它會自動查找在context中定義的MessageSource bean這個bean必須交做messageSource如果找了這樣一個bean所有對上述方法的調用將被委托給找到的messageSource如果沒有找到messageSourceApplicationContext將會嘗試查找他的父親是否包含有同名的bean如果有它將把找到的bean作為MessageSource如果他沒有找到任何的信息處理源他會創建一個StaticMessageSource
Spring目前提供了兩個MessageSource的實現他們是
ResourceBundleMessageSource和StaticMessageSource兩者都實現了NestingMessageSource一邊能夠處理嵌套的信息StaticMessageSource很少被使用但是他提供了編程的方式向source增加信息我們經常使用的是ResourceBundleMessageSource
在Spring中使用資源
ApplicationContext繼承了ResourceLoader接口在這個接口中定義了getResource()方法如下
Resource getResource(String location)
該方法返回一個資源句柄這個句柄應該總是一個可重復使用的資源描述符允許多次調用getInputStream();
getResource()方法的參數是一個資源訪問地址例如
file:\c:/testdata
classpath:testdata(從classpath路徑中查找testdat文件並返回他的資源句柄)
WEBINF/testdat
注意getResource()方法返回的Resource句柄並不意味著資源實際存在你需要調用Resource接口的exists()方法判斷資源是否存在
Resource提供了與協議無關的特性
事件傳遞
ApplicationContext中的時間處理是通過AppcationEvent類和ApplicationListener接口來提供的如果上下文中部署了一個實現了ApplicationListener接口的bean每次一個ApplicationEvent發布到ApplicationContext時那個bean就會被通知實質撒謊功能這是標准的Observer設計模式
Spring提供的三個標准事件
a ContextRefreshedEvent
當ApplicationContext已經初始化或刷新後發送的事件這裡初始化意味著所有的bean被裝載singleton被預實例化以及ApplicationContext已經准備好
b ContextClosedEvent
當使用ApplicationContext的close()方法結束上下文的時候發送的事件這裡意味著singleton被銷毀
c RequestHandledEvent
一個與web相關的事件告訴所有的bean一個HTTP請求已經被響應了(這個時間將會在一個請求結束後被發送—)注意這個時間只能應用於使用了Spring的DispatcherServlet的web應用
=========================================================================================
LifeCycle
InitializingBean/initmethod
實現orgspringframeworkbeansfactoryInitializingBean接口允許一個bean在他的所有必需的屬性被BeanFactory設置後來執行初始化的工作
當然可以使用initmethod來取代實現這個接口以讓應用不與spring產生耦合
如果一個bean既實現了InitializingBean又指定了initmethod則spring會先調InitializingBean的方法在調initmethod指定的方法
DisposableBean/destroymethod
實現orgspringframeworkbeansfactoryDisposableBean接口允許一個bean可以在包含他的BeanFactory銷毀的時候得到一個回調
注意BeanFactory對bean的管理默認是單實例的如果bean不是單示例的spring就不能管理他的生命周期
BeanFactoryAware
對於實現了orgspringframeworkbeansfactoryBeanFactoryAware接口的類當它被BeanFactory創建後它會擁有一個指向創建他的BeanFactory的引用
BeanNameAware
如果一個bean實現了orgspringframeworkbeansfactoryBeanNameAware接口並且被部署到一個BeanFactory中那麼BeanFactory就會通過這個接口來調用bean以便通知這個bean他被部署的id這個回調發生在普通的bean屬性設置之後在初始化回調之前比如InitializingBean的afterProperteis方法(或者自定義的initmethod)
Bean的生命周期如下
Bean的構造
調用setXXX()方法設置Bean的屬性
調用BeanNameAware的setBeanName();
調用BeanFactoryAware的setBeanFactory()方法
調用BeanPostProcessor的postProcessBeforeInitialization()方法
調用InitializingBean的afterPropertiesSet()方法
調用自定義的初始化方法
調用BeanPostProcessor類的postProcessAfterInitialization()方法
調用DisposableBean的destroy()方法
調用自定義的銷毀方法
========================================================================================
擴展Spring的Ioc框架
Spring框架的IoC組件被設計為可擴展的通常應用開發者並不需要子類化各個BeanFactory或ApplicationContext的實現類通過插入特定接入接口的實現Spring的IoC容器就可以不受限制的進行擴展
BeanPostProcessor:在創建bean之後調用
BeanFactoryPostProcessors在創建bean之前調用
如果想在spring容器完成一個bean的實例化後再對他進行初始化之前或之後執行一些自定義的邏輯可以插入一個或多個BeanPostProcessor的實例
orgspringframewonfigBeanPostProcessor接口包含了兩個回調方法當一個類作為容器的後置處理器(postprocessor)被注冊後對於由容器創建的每個bean實例在任一個初始化方法(例如afterProperties和利用initmethod聲明的方法)調用前後後置處理器會從容器中分別獲取一個回調後置處理器可以隨意對這個bean實例執行他所期望的動作也包括完全忽略這個回調
BeanFactory和ApplicationContext對待bean後置處理器稍有不同
ApplicationContext會自動檢測任何提供給他的在配置元數據中定義實現了BeanPostProcessor接口的bean並把它們注冊為後置處理器然後在容器創建bean的適當時候調用它部署一個後置處理器同部署其他的bean並沒有什麼區別無需其他的動作而另一方面當使用BeanFactory的時候bean後置處理器鼻息編寫代碼顯示的去注冊
我們看到的下一個擴展點是
orgspringframewonfigBeanFactoryPostProcessor出一個主要的區別外這個接口的寓意類似於BeanPostProcessorBeanFactoryPostProcessor作用於bean的定義上(例如提供給容易的配置元數據)也就是說Spring IoC容器允許BeanFactoryPostProcessor在容易實際實例化任何bean之前讀取配置元數據並可能修改它
Spring包含了許多已有的bean工廠後置處理器例如PropertyResourceConfigure和PropertyPlaceHolderConfigure以及 BeanNameAutoProxyCreator
在一個BeanFactory中應用BeanFactoryPostProcessor需要手工編碼實現而ApplicationContext則會檢測部署在它之上實現了BeanFactoryPostProcessor接口的bean並在適當的時候自動把它們用做bean工作後置處理器部署一個後置處理器同部署其他的bean並沒有什麼區別無需其他的動作
PropertyPlaceholderConfigurer
作為一個bean工廠後置處理器的實現可以用來將BeanFactory定義中的一些屬性值放置到另一個單獨的Java Properties格式的文件中這就允許用戶在部署應用的時候定制一些關鍵屬性(例如數據庫URL用戶名和密碼)而不用對主XML定義文件或容器所用文件進行復雜和危險的修改
PropertyOverrideConfigurer
類似於PropertyPlaceholderConfigurer但是與後者相比前者對於bean屬性可以有卻興致或者根本沒有值如果起覆蓋左右的Properties文件沒有某個bean屬性的內容那麼將使用卻行的上下文定義
bean工廠的定義並不會議室到被覆蓋所以僅僅擦看XML定義文件並不能立刻明顯的知道覆蓋配置是否被起作用了在多個PropertyOverrideConfigurer對一個bean屬性定義了不同的值的時候最後一個將取勝
***他使用beanNamepropertyName來指定值而且不需要在bean中進行配置
注冊用戶自定義的PropertyEditors
a當用字符串值設置bean的屬性時BeanFactory實質上使用了標准的JavaBeans的PropertyEditor將這些String轉換為屬性的復雜類型Spring預先注冊了很多定制的PropertyEditor(比如將一個字符串表示我的classname轉換成陣陣的Class對象)
b 要編寫一個屬性編輯器可以實現PropertyEditor接口更為簡便的方式是從PropertyEditorSupport類繼承
要使用自定義的PropertyEditors必須使用orgspringframewonfigCustomEditorConfigurer來注冊自定義的屬性編輯器
FactoryBean可以用來做代理
orgspringframeworkbeansfactoryFactoryBean
**要想得到FactoryBean本身需要在beanName前面加上&即&beanName
*********BeanFactory和ApplicationContext的區別*********
ApplicationContext是在ApplicationContext初始化的時候就把所有的bean都創建好了並存放在緩存中
BeanFactory是在需要得到bean的時候才去創建他的實例
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28565.html