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 就失去了延迟的效果。
<