spring之bean的生命周期

上篇文章中,详细介绍了spring中bean的scope,scope既是bean在spring容器中的存在方式,如prototype和singleton,且也带了一些存在周期的属性,如 session和request等。spring中 bean从实例化,到依赖注入、再到初始化、到最后消亡,有和完整的生命周期。它和scope一起构成bean完整的生命周期。本篇文章主要简单的描述下bean生命周期中的初始化方法(init())和消亡前(ondestroy(),以后称之为析构)的方法。本文主要讨论scope为prototype和singleton的bean,且由于prototype的bean在返回给客户端后,spring不在由spring进行管理,所以其销毁前的方法不会执行。

spring中bean的生命周期简单的如下图所示:

我们可以在生命周期函数中加入自己的一些定制化处理,,比如说在初始化阶段,加载相关的资源,启动线程等,在析构阶段释放资源,关闭线程。需要牢记一点,初始化函数是在所有的依赖已经注入后才开始执行的。

生命周期回调

其中中bean的初始化和消亡前主要由以下几种方式:

1.Spring的接口InitializingBean和DisposableBean。示例如下:

/*** InitializingBean 接口从名字可以看出此方法在 bean的属性被spring赋值之后执行,但是和spring的接口耦合在了一起 */ @Override public void afterPropertiesSet() throws Exception {System.out.println(this+" i am afterPropertiesSet"); }/* ** DisposableBean 接口定义的*/ @Override public void destroy() throws Exception {System.out.println(this+" i am destroy"); }2.采用元数据配置,即在bean的定义中配置,如属性,直接定义相关方法,另外在根标签<beans>可以配置default-init-method 和default-destroy-method 配置默认的 方法,如果<bean>中有定义,则覆盖默认的定义:<bean id="user0" class="com.test.service.UserServiceIml" init-method="testInit" destroy-method="testBeforeDesstroy"><property name="userDao" ref="userDao"></property></bean> /*** @Description: 采用元数据配置,在xml中配置 * @param* @return void */ public void testInit(){System.out.println(this+" i am testInit"); }/*** @Description: 采用元数据配置,在xml中配置 * @param* @return void */ public void testBeforeDesstroy(){System.out.println(this+" i am testBeforeDesstroy"); }3.采用JSR注解/*** @Description: 采用jsr注解 * @param* @return void */ @PostConstruct public void testPostConstruct(){System.out.println(this+" i am testPostConstruct"); }/*** @Description: 采用JSR的注解 * @param* @return void */ @PreDestroy public void testPreDesstroy(){System.out.println(this+" i am testPreDesstroy"); }混合机制

以上有三种回调函数实现的方式,他们可以单独使用,也可以混合使用,混合使用的时候,他们的顺序如下:

对于初始化函数:

1.@PostConstruct 注解的方法

2.InitializingBean接口定义的回调afterPropertiesSet()

3.Bean配置中自定义的初始化函数

对于析构则与上相同:

1.@PreDestroy注解的方法

2.DisposableBean接口定义的回调destroy()

3.Bean配置中自定义析构函数

详细的测试见后面。

startUp和shutDown回调

有时候我们可能需要一些组件的功能随着spring容器的启动而启动(如新开启一个线程来进行监听),容器的销毁而销毁。为此spring提供了一个接口,从方法名字很容易看到方法的作用:

public interface Lifecycle {void start();void stop();boolean isRunning(); }当启动的时候,由于组件之间的依赖,启动的顺序是相当重要的。depends-on属性可以决定多个lifecycle的实现的顺序,但是有时候依赖是未知的。为此spring定义可一个新的接口,SmartLifecycle:public interface Phased {int getPhase(); } public interface SmartLifecycle extends Lifecycle, Phased {boolean isAutoStartup();void stop(Runnable callback); }isAutoStartup决定是随着容器的启动自启动,Phased接口定义的方法则决定了启动顺序,其返回值越小启动越早,越大启动越晚。如果一个Lifecycle未实现Phased接口,则默认其值为0.

Stop方法可以异步的执行析构函数,spring默认会为每一个Phase等待30秒钟。这个时间是可以配置的。

测试

在非web环境下,要使析构函数执行,需要执行AbstractApplicationContext的registerShutdownHook()方法,见本文的示例:

本测试准备说明以下:

1.混合生命周期回调的执行顺序

2.LifeCycle也可以看做为周期,其中start方法在初始化函数执行后被调用,stop方法在析构函数执行前被调用。Prototype 不会被调用start和 stop方法

3.Depend-on决定bean加载的顺序

4.<bean>定义的回调会覆盖<beans>定义的默认的回调。

代码

以下是测试程序,本程序依赖Spring之容器和配置初识这篇文章中的代码,并对其稍加改动:

代码结构如下:

首先是allbean.xml配置文件:

<!–使JSR注解生效 –><bean id="postsss" class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/> <!– 也可以使用这个配置 使JSR生效 <context:annotation-config/> –><!– 改变在容器关闭阶段,smartlifecycle 每个阶段 等待的时间 –><bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor"><!– timeout value in milliseconds –><property name="timeoutPerShutdownPhase" value="3000"/> </bean><import resource="com/test/dao/dao.xml"/><import resource="com/test/service/service.xml"/>待人对事不要太计较,如果太计较就会有悔恨!

spring之bean的生命周期

相关文章:

你感兴趣的文章:

标签云: