1、Bean的作用域

(1)標(biāo)注scope為singleton或者缺省scope屬性的Bean在ApplicationContext(IOC容器為BeanFactory非ApplicationContext實(shí)現(xiàn)類則不會(huì))啟動(dòng)時(shí)就會(huì)自動(dòng)實(shí)例化,并且從容器啟動(dòng)到銷毀只存在一個(gè)實(shí)例,容器負(fù)責(zé)這個(gè)實(shí)例的全部生命周期的管理。
(2)標(biāo)注scope為prototype的Bean只在IOC容器的getBean()方法被調(diào)用時(shí)才會(huì)進(jìn)行實(shí)例化,并且每次調(diào)用該方法返回的都是不同的實(shí)例。
(3)標(biāo)注socpe為request的Bean對(duì)于每一次request都將產(chǎn)生不同Bean實(shí)例,并且在一次request結(jié)束后Bean的實(shí)例將銷毀。
(4)標(biāo)注scope為session的Bean對(duì)于每次session會(huì)話都只產(chǎn)生一個(gè)Bean實(shí)例,并且在session失效后自動(dòng)銷毀。
(5)當(dāng)一個(gè)bean的作用域?yàn)镚lobal Session,表示在一個(gè)全局的HTTP Session中,一個(gè)bean定義對(duì)應(yīng)一個(gè)實(shí)例。典型情況下,僅在使用portlet context的時(shí)候有效。該作用域僅在基于web的Spring ApplicationContext情形下有效。
需要注意的是,后面三種作用域只針對(duì)web應(yīng)用。
2、Bean的生命周期

Bean實(shí)例生命周期的執(zhí)行過程如下:
Spring對(duì)bean進(jìn)行實(shí)例化,默認(rèn)bean是單例;
Spring對(duì)bean進(jìn)行依賴注入;
如果bean實(shí)現(xiàn)了BeanNameAware接口,spring將bean的id傳給setBeanName()方法;
如果bean實(shí)現(xiàn)了BeanFactoryAware接口,spring將調(diào)用setBeanFactory方法,將BeanFactory實(shí)例傳進(jìn)來(lái);
如果bean實(shí)現(xiàn)了ApplicationContextAware接口,它的setApplicationContext()方法將被調(diào)用,將應(yīng)用上下文的引用傳入到bean中;
如果bean實(shí)現(xiàn)了BeanPostProcessor接口,它的postProcessBeforeInitialization方法將被調(diào)用;
如果bean實(shí)現(xiàn)了InitializingBean接口,spring將調(diào)用它的afterPropertiesSet接口方法,類似的如果bean使用了init-method屬性聲明了初始化方法,該方法也會(huì)被調(diào)用;
如果bean實(shí)現(xiàn)了BeanPostProcessor接口,它的postProcessAfterInitialization接口方法將被調(diào)用;
此時(shí)bean已經(jīng)準(zhǔn)備就緒,可以被應(yīng)用程序使用了,他們將一直駐留在應(yīng)用上下文中,直到該應(yīng)用上下文被銷毀;
若bean實(shí)現(xiàn)了DisposableBean接口,spring將調(diào)用它的destroy()接口方法。同樣的,如果bean使用了destroy-method屬性聲明了銷毀方法,則該方法被調(diào)用;
不管何種作用域,容器都會(huì)調(diào)用所有對(duì)象的初始化生命周期回調(diào)方法。但對(duì)prototype而言,任何配置好的析構(gòu)生命周期回調(diào)方法都將不會(huì)被調(diào)用(在scope為prototype的Bean中配置destroy-method屬性無(wú)效)。清除prototype作用域的對(duì)象并釋放任何prototype bean所持有的昂貴資源(如數(shù)據(jù)庫(kù)連接資源),都是客戶端代碼的職責(zé)(讓Spring容器釋放被prototype作用域bean占用資源的一種可行方式是,通過使用bean的后置處理器,該處理器持有要被清除的bean的引用)。
例子:
定義兩個(gè)類Source、JuiceMaker,都實(shí)現(xiàn)BeanNameAware、BeanFactoryAware、ApplicationContextAware、InitializingBean接口。
定義類MyPostProcessorImpl實(shí)現(xiàn)BeanPostProcessor接口、MyDisposableImpl實(shí)現(xiàn)DisposableBean接口
代碼如下:
Source:
public class Source implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean{
private String fruit;
private String sugar;
private String size;
/**getter and setter*/
.....
public void setBeanName(String name) {
System.out.println("【Source】調(diào)用BeanNameAware接口的setBeanName方法");
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("【Source】調(diào)用BeanFactory接口的setBeanFactory方法");
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("【Source】調(diào)用ApplicationContext接口的setApplicationContext方法");
}
public void afterPropertiesSet() throws Exception {
System.out.println("【Source】調(diào)用InitializingBean接口的afterPropertiesSet方法");
}
//自定義初始化和銷毀方法
public void init() {
System.out.println("【Source】調(diào)用自定義初始化方法初始化");
}
public void destroy() {
System.out.println("【Source】調(diào)用自定義銷毀方法");
}
}
JuiceMaker的代碼和Source類似就不貼出來(lái)了,下面來(lái)看MyPostProcessorImpl和MyDisposableImpl的代碼:
MyPostProcessorImpl:
public class MyPostProcessorImpl implements BeanPostProcessor{
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("【MyPostProcessor】" + bean.getClass().getSimpleName() + "的對(duì)象" + beanName + "開始初始化");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("【MyPostProcessor】" + bean.getClass().getSimpleName() + "的對(duì)象" + beanName + "初始化完成");
return bean;
}
}
MyDisposableImpl:
public class MyDisposableImpl implements DisposableBean{
public void destroy() throws Exception {
? System.out.println("【MyDisposableImpl】調(diào)用DisposableBean接口destroy方法");
}
}
在配置文件中配置bean:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
? ? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
? ? xsi:schemaLocation="http://www.springframework.org/schema/beans
? ? http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean id="source" class="spring.chapter9.ioc.Source" init-method="init" destroy-method="destroy">
<property name="fruit" value="橙子" ></property>
<property name="sugar" value="三勺" />
<property name="size"? value="大杯" />
</bean>
<bean id="juiceMaker" class="spring.chapter9.ioc.JuiceMaker" init-method="init" destroy-method="destroy">
? ? <property name="shopName" value="布拉格" />
? ? <property name="source"? ref="source" />
</bean>
<bean id="beanPostProcessor" class="spring.chapter9.lifecycle.MyPostProcessorImpl" />
<bean id="beanDisposable" class="spring.chapter9.lifecycle.MyDisposableImpl" />
</beans>
注意加粗的部分,分別給bean指定自定義的初始化和銷毀方法.
測(cè)試:
public class Test {
private static ApplicationContext ctx;
public static void main(String[] args) {
ctx =
new ClassPathXmlApplicationContext("classpath:spring-cfg-ioc.xml");
JuiceMaker juiceMaker = (JuiceMaker) ctx.getBean("juiceMaker");
juiceMaker.make();
}
由此可見BeanNameAware、BeanFactoryAware、ApplicationContextAware、InitializingBean接口都是針對(duì)單個(gè)Bean而言的,而BeanPostProcessor接口則是針對(duì)每一個(gè)Bean(當(dāng)然不包括實(shí)現(xiàn)了這個(gè)接口的Bean本身)。DisposableBean是針對(duì)Spring IoC容器的。
另外需要注意的是,afterPropertiesSet方法執(zhí)行完后,如果沒有自定義初始化方法,那么Bean的初始化和依賴注入已經(jīng)完成了。