9.3.3、Bean的生命周期

2018-11-11  本文已影响0人  john_leventon

1、Bean的作用域

在配置文件中用属性scope标注

(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的初始化和依赖注入已经完成了。

上一篇下一篇

猜你喜欢

热点阅读