1、Bean的作用域
(1)标注scope为singleton或者缺省scope属性的Bean在ApplicationContext(IOC容器为BeanFactory非ApplicationContext实现类则不会)启动时就会自动实例化,并且从容器启动到销毁只存在一个实例,容器负责这个实例的全部生命周期的管理。
(2)标注scope为prototype的Bean只在IOC容器的getBean()方法被调用时才会进行实例化,并且每次调用该方法返回的都是不同的实例。
(3)标注socpe为request的Bean对于每一次request都将产生不同Bean实例,并且在一次request结束后Bean的实例将销毁。
(4)标注scope为session的Bean对于每次session会话都只产生一个Bean实例,并且在session失效后自动销毁。
(5)当一个bean的作用域为Global Session,表示在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于web的Spring ApplicationContext情形下有效。
需要注意的是,后面三种作用域只针对web应用。
2、Bean的生命周期
Bean实例生命周期的执行过程如下:
Spring对bean进行实例化,默认bean是单例;
Spring对bean进行依赖注入;
如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法;
如果bean实现了BeanFactoryAware接口,spring将调用setBeanFactory方法,将BeanFactory实例传进来;
如果bean实现了ApplicationContextAware接口,它的setApplicationContext()方法将被调用,将应用上下文的引用传入到bean中;
如果bean实现了BeanPostProcessor接口,它的postProcessBeforeInitialization方法将被调用;
如果bean实现了InitializingBean接口,spring将调用它的afterPropertiesSet接口方法,类似的如果bean使用了init-method属性声明了初始化方法,该方法也会被调用;
如果bean实现了BeanPostProcessor接口,它的postProcessAfterInitialization接口方法将被调用;
此时bean已经准备就绪,可以被应用程序使用了,他们将一直驻留在应用上下文中,直到该应用上下文被销毁;
若bean实现了DisposableBean接口,spring将调用它的destroy()接口方法。同样的,如果bean使用了destroy-method属性声明了销毁方法,则该方法被调用;
不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法。但对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用(在scope为prototype的Bean中配置destroy-method属性无效)。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源(如数据库连接资源),都是客户端代码的职责(让Spring容器释放被prototype作用域bean占用资源的一种可行方式是,通过使用bean的后置处理器,该处理器持有要被清除的bean的引用)。
例子:
定义两个类Source、JuiceMaker,都实现BeanNameAware、BeanFactoryAware、ApplicationContextAware、InitializingBean接口。
定义类MyPostProcessorImpl实现BeanPostProcessor接口、MyDisposableImpl实现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】调用BeanNameAware接口的setBeanName方法");
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("【Source】调用BeanFactory接口的setBeanFactory方法");
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("【Source】调用ApplicationContext接口的setApplicationContext方法");
}
public void afterPropertiesSet() throws Exception {
System.out.println("【Source】调用InitializingBean接口的afterPropertiesSet方法");
}
//自定义初始化和销毁方法
public void init() {
System.out.println("【Source】调用自定义初始化方法初始化");
}
public void destroy() {
System.out.println("【Source】调用自定义销毁方法");
}
}
JuiceMaker的代码和Source类似就不贴出来了,下面来看MyPostProcessorImpl和MyDisposableImpl的代码:
MyPostProcessorImpl:
public class MyPostProcessorImpl implements BeanPostProcessor{
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("【MyPostProcessor】" + bean.getClass().getSimpleName() + "的对象" + beanName + "开始初始化");
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("【MyPostProcessor】" + bean.getClass().getSimpleName() + "的对象" + beanName + "初始化完成");
return bean;
}
}
MyDisposableImpl:
public class MyDisposableImpl implements DisposableBean{
public void destroy() throws Exception {
System.out.println("【MyDisposableImpl】调用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指定自定义的初始化和销毁方法.
测试:
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接口都是针对单个Bean而言的,而BeanPostProcessor接口则是针对每一个Bean(当然不包括实现了这个接口的Bean本身)。DisposableBean是针对Spring IoC容器的。
另外需要注意的是,afterPropertiesSet方法执行完后,如果没有自定义初始化方法,那么Bean的初始化和依赖注入已经完成了。