- Singleton : 在每個Spring IoC容器中一個bean定義對應一個物件實例。
- prototype : 一個bean定義對應多個物件實例。
- request : 在一次HTTP請求中,一個bean定義對應一個實例;即每次HTTP請求將會有各自的bean實例,
它們依據某個bean定義創建而成。該作用域僅在基於web的Spring ApplicationContext情形下有效。 - session : 在一個HTTP Session中,一個bean定義對應一個實例。該作用域僅在基於web的Spring ApplicationContext
情形下有效。 - global session : 在一個全局的HTTP
Session中,一個bean定義對應一個實例。典型情況下,
僅在使用portlet context的時候有效。該作用域僅在基於web的SpringApplicationContext情形下有效。
Spring預設的bean instance皆為 Singleton, 也就是說當請求要一個bean的時候,有點類似到bean pool當中
找尋一個已存在的bean by id,若找不到則create new one.
prototype 的scope最適合用於處理 stateful bean,ioc container會針對每次的請求重新產生一個bean實體並傳回,
而stateless的bean則可建議採用singleton , 唯一要特別注意的是使用prototype scope bean, Bean lifecycle則由client端自行負責。像DAO這類的物件就應該可以設置為Singleton
如果我們要將一個prototype bean 注入到一個 singleton bean時,必須注意到,此時container是先產生了一個prototype bean instance並且注入到 singleton bean,但此項行為只會發生一次,若想要每次在singleton bean當中都能取得新的prototype bean,則不能這麼做,必須參考Method injection方式進行。
Request , Session , Global Session都是針對 web applicaiton所設置的,必須在web.xml中設定listener,才能正確使用IoC container,設置說明如下:
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
若是較早期的Servlet 2.3 則使用 javax.servlet.Filter方式設定
<filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
IoC container除了是專門再處理bean 實體化過程的管理者以外,也是作為一個bean instance之間合作關係(將bean之間wiring up)的一個關係人,舉例要把一個request scope bean 注入到另一個bean,我們必須提供一個AOP proxy的bean來作為共同存取的介面,也就是說,你需要注入一個代理物件,該物件具有與被代理物件一樣的公共介面,而容器則可以足夠智能的從相關作用域中(比如一個HTTP request)獲取到真實的目標物件,並把方法調用委派給實際的物件。
特別注意的是 <aop:scoped-proxy>不能搭配在singleton , prototype使用,否則會BeanCreationException
以下這範例可以參考如何設置兩個不同bean scope的介面關係
<bean id="userPreferences" scope="session">
<!-- this next element effects the proxying of the surrounding bean -->
<aop:scoped-proxy/>
</bean>
<bean id="userService" class="com.foo.SimpleUserService">
<property name="userPreferences" ref="userPreferences"/>
</bean>
在上面的範例中可以看到,我們在一個singleton bean - userService當中注入了一個 session scope bean - userPrefrences,這也就是說 userService被初始化過一次(也僅一次),而同時也將其相依的userPreferences初始化一次,接著僅永遠操作同一個物件了,這樣的實體處理方式並不是正確的,session是會被改變的,而為了可以正確的去使用到session scope bean,我們必須透過一個proxy介面,以類別的型式去呼叫存取bean實體,所以才加入了<aop:scoped-proxy>,而此時需要在classpath中加入cglib.jar,像這樣的一個proxy物件他實做了userPreferencs的公用介面,而被注入的 bean也不會需要知道proxy而來的物件實體是哪一種 scope,反正他確實可以執行呼叫就行了。但必須注意的是,cglib能夠 proxy的 method,僅有public demacrated的 methods.
#Customizing the nature of a bean
雖然 IoC Container是專門在管理 bean instance生命週期的,但有時候我們仍會需要自己來做一些控制行為,這時候就需要了解一下how to control @@,那麼為了要能自行管理bean instance,我們需要做一些特別的事情:
- implements InitializingBean , DisposableBean
IoC container 會透過呼叫 afterPropertiesSet() ,以及 destroy()來進行物件的初始化作業以及gc處理。當然我們也可以自己透過設定的方式達成這兩件事情,就是在bean定義中去加入 init-method宣告即可。而在spring framework核心裡頭,是由BeanPostProcessor來實作處理所有的 callback interfaces,若要特定的 callback處理作法,則可以自己實作BeanPostProcessor。
afterPropertiesSet 是指當 container將所有必要的資訊都設定至bean完成之後開始進行的初始化作業,而 destory()則是解構子用途,一般情形下我們不太需要自己來撰寫這兩個 method,頂多可以在 <bean> tag宣告 init-method, destroy-method,而這兩者其實等同於 non-arg constructor,以及一個自訂的 解構函式 (like release resource)
在開發一個系統時,其實可以統一命名一個init/destroy的method name,將之寫在 <beans default-init-method="init" >,同理,也可以寫一個default-destroy-method,每一個bean再遇到有特殊init狀況時,則在<bean init-method>中撰寫即可。
沒有留言:
張貼留言