Bean 的生命周期及作用域
在 BeanFactory 中 Bean 的生命周期:
1、 容器寻找 Bean 的定义信息并将其实例化。
2、 使用依赖注入, spring 按照 Bean 定义信息配置 Bean 的所有属性。
3、 如果 Bean 实现了 BeanNameAware 接口,工厂调用 Bean 的 setBeanName() 方法传递 Bean 的 id 。
4、 如果 Bean 实现了 BeanFactoryAware 接口,工厂调用 setBeanFactory() 方法传入工厂自身。
5、 如果有 BeanPostProcessor 和 Bean 关联,那么其 postProcessBeforeInitialization() 方法将调被调用
6、 如果 Bean 指定了 init — method 方法,将被调用
7、 如果有 BeanPostProcess 和 Bean 关联,那么其 postProcessAfterInitialization() 方法将被调用。
Bean 在加载容器时创建 、 Bean 初始化时执行 init-method 方法、 Bean 被关闭时执行 destory-method 方法。
消除 BeanFactory 中 bean 的方法:
1、 如果 Bean 实现了 DisposableBean 接口, destory() 方法被调用
2、 如指定了定制的销毁方法,就调用这个方法
注: Bean 的 spring 应用上下文中的生命周期与在 BeanFactory 中的生命周期只有一点不同:即 Bean 实现了 ApplicationContextAware 接口, setApplicationContext() 放法会被调用。
案例:简单介绍 Bean 的生命周期
public class CycleLifeService implements BeanNameAware, BeanFactoryAware,BeanPostProcessor{
private String say ;//say 的属性
private Test test ;//java 类的实例
public void setSay(String say) {
this . say = say;
}
public Test getTest() {
return test ;
}
public void setTest(Test test) {
this . test = test;
}
public void test(){
System. out .println( "-------------" + this . say );
}
// 初始化的方法
public void init(){
System. out .println( " 初始化方法 ...." );
}
// 销毁的方法
public void destroy(){
System. out .println( " 销毁方法 ....." );
}
// 设置 Bean 的 name
@Override
public void setBeanName(String name) {
System. out .println( "====" +name);
}
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
// 设置一个 beanFactory
System. out .println(BeanFactory. class );
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System. out .println( "------ 后 " +beanName);
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System. out .println( "-------- 前 " +beanName);
return bean;
}
}
Test 的类
public class Test {
public void test() {
System. out .println( "======================" );
}
}
applicationContext.xml 文件
文件中定义的初始化的方法和销毁的方法
< bean id = "cycleLifeService" class = "cn.csdn.cyclelife.CycleLifeService"
init-method = "init" destroy-method = "destroy" >
< property name = "say" >
< value > 你好!!! </ value >
</ property >
< property name = "test" >
< ref bean = "test" ></ ref >
</ property >
</ bean >
< bean id = "test" class = "cn.csdn.cyclelife.Test" />
其中的 init-method 方法在 Bean 实例化时被调用; destory-method 方法在 Bean 从容器删除之前被调用
Bean 的作用域
Spring Framework 支持五种作用域(其中有三种只能用在基于 web 的 Spring ApplicationContext
)。
1 、 singleton :在每个Spring IoC 容器中一个bean 定义对应一个对象实例。( 在初始化容器时,创建一个 bean 的实例对象 )
2 、 prototype : 一个bean 定义对应多个对象实例。( 在每次请求该 bean 时,都会创建一个 bean 的实例对象 )
3 、 request :在一次HTTP 请求中,一个bean 定义对应一个实例;即每次HTTP 请求将会有各自的bean 实例,它们依据某个bean 定义创建而成。该作用域仅在基于web 的Spring ApplicationContext
情形下有效。
4 、 session: 在一个HTTP Session
中,一个bean 定义对应一个实例。该作用域仅在基于web 的Spring ApplicationContext
情形下有效。
5 、 global session :在一个全局的HTTP Session
中,一个bean 定义对应一个实例。典型情况下,仅在使用portlet context 的时候有效。该作用域仅在基于web 的Spring ApplicationContext
情形下有效。
我们在 spring 中常用的两种作用域: singleton 和 prototype 一下主要详细介绍该两种作用域。
第一种 :
Singleton 作用域:
当把一个 bean 定义设置为 singlton 作用域时, Spring IoC 容器只会创建该 bean 定义的唯一 实例。这个单一实例会被存储到单例缓存( singleton cache )中,并且所有针对该 bean 的后续请求和引用 都将返回被缓存的对象实例。
< bean id = "studentServiceImpl" class = "cn.csdn.service.StudentServiceImpl"
scope = "singleton" >
< property name = "studentDaoImpl" ref = "studentDaoImpl" >
</ property >
</ bean >
public class StudentServiceImpl {
private StudentDaoImpl studentDaoImpl ;
public void setStudentDaoImpl(StudentDaoImpl studentDaoImpl) {
this . studentDaoImpl = studentDaoImpl;
}
@Override
public void insert() {
studentDaoImpl .insert();
}
}
public class StudentDaoImpl {
@Override
public void insert() {
System. out .println( " 插入成功 ....." );
}
}
第二种:
Prototype 作用域:
Prototype 作用域的 bean 会导致在每次对该 bean 请求(将其注入到另一个 bean 中,或者以程序的方式调用容器的 getBean()
方法)时都会创建一个新的 bean 实例 。根据经验,对所有有状态的 bean 应该使用 prototype 作用域,而对无状态的 bean 则应该使用 singleton 作用域。
注: Spring 不能对一个 prototype bean 的整个生命周期负责:容器在初始化、配置、装饰或者是装配完一个 prototype 实例后,将它交给客户端,随后就对该 prototype 实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对 prototype 而言,任何配置好的析构生命周期回调方法都将不会 被调用。清除 prototype 作用域的对象并释放任何 prototype bean 所持有的昂贵资源,都是客户端代码的职责。
<!-- 使用 singleton 模式创建 bean 实例对象 -->
< bean id = "cityService" class = "cn.csdn.service.CityService" scope = "prototype" ></ bean >
补充:延迟初始化:
依赖:
延迟初始化 :lazy-init:false true;
false: 加载容器时 初始化对象
true :第一次调用时初始化对象
在跟标签中有一个 default-lazy-init 的属性 如果该属性设置为 true 该文件中的所有 bean 都会被延迟初始化。
注意:如果在 lazy-init ='false' 的 bean 中,引用 lazy-init ="true" 的 bean, 那么 lazy-init 就失去了延迟的效果。
< bean id = "empService" class = "cn.csdn.service.EmpService" scope = "singleton" lazy-init = "true" >
</ bean >