spring学习(七)——spring官方文档阅读(5.0.7)——生命周期回调

这个章节官方文档写的很乱,这些是自己验证后所写,如有错误,欢迎指出

生命周期回调

我们可以实现InitializingBean和DisposableBean接口。容器会调用前者的afterPropertiesSet()方法,调用后者的destory()方法,以允许在初始化和销毁bean时执行某些操作,也可以使用@PostConstruct和@PreDestory注解来实现生命周期回调,通过BeanPostProcessor实现类,Spring可以找到任何回调接口的实现类并调用适当的方法。

初始化回调

建议使用注解@PostConstruct,可以防止应用与spring容器耦合,对于xml配置,可以通过下述方式防止代码耦合:

<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
public class ExampleBean {

    public void init() {
        // do some initialization work
    }
}

上述方式等效于:

<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
public class AnotherExampleBean implements InitializingBean {

    public void afterPropertiesSet() {
        // do some initialization work
    }
}

销毁回调

建议使用注解@PreDestory,对于XML配置,采用下述方法防止代码耦合:

<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
public class ExampleBean {

    public void cleanup() {
        // do some destruction work (like releasing pooled connections)
    }
}

上述方式等效于:
 

<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
public class AnotherExampleBean implements DisposableBean {

    public void destroy() {
        // do some destruction work (like releasing pooled connections)
    }
}

destory-method可以指定为一个特殊值——inferred,此时spring会自动匹配指定bean中的close或是shutdown方法。

 

默认的初始化和销毁方法

通过指定<beans/>的default-init-method、default-destroy-method属性,可以让spring在每次创建完一个对象后或是销毁一个对向前调用相应的方法(如果存在),不必每次在<bean>中指明init-method或是destroy-method的值,我们可以通过在<bean>中指明init-method或是destroy-method的值来覆盖default-init-method、default-destroy-method的值,当所有依赖都已经注入bean后,spring才会执行init-method和default-init-method指定的函数,当一个bean完全创建完毕后,AOP拦截链和代理才会开始执行(配置了AOP的情况),将拦截器应用到init-method指定的方法是不明智的,此时会将bean的创建与拦截器结合起来

 

结合生命周期的机制

在spring2.5中,有三种选择来控制bean生命周期的行为:

1、InitializingBean、DisposableBean

2、init-method、destroy-method的值

3、@PostConstruct和@PreDestory

我们可以糅合这几种机制

使用不同的方法为同一bean配置多个初始化生命周期,调用顺序如下:


1、@PostConstruct

2、InitializingBean 中的afterPropertiesSet()

3、init-method的值

 

使用不同的方法为同一bean配置多个销毁生命周期,调用顺序如下:
 

1、@PreDestory

2、DisposableBean中的destory()

3、destroy-method的值

 

启动和关闭回调

当SpringIOC容器启动后或是关闭前,我们想启动或是停止一些后台进程,此时可以使用启动和关闭回调

Lifecycle接口:

public interface Lifecycle {

    //接收到start信号时,若isRunning返回为false,则调用
    void start();

    //接收到stop信号时,若isRunning返回true,则调用
    void stop();

    //返回的boolean值将决定容器接收到启动或是停止命令时是运行start还是stop
    boolean isRunning();
}

在容器刷新阶段(关闭并重启BeanFactory),不会接收到stop信号,在容器自启动(不是显式调用start方法)阶段,不会接收到start信号,如果想对Bean提供更加精确的控制,可以考虑继承实现SmartLifecycle,容器关闭时,若isRunning()返回true,将会调用所有实现了Lifecycle的bean的stop方法,接着调用销毁方法,如果是刷新(刷新时会销毁已经存在BeanFactory),此时只会调用bean的销毁方法,spring通过LifecycleProcessor的实现类来处理生命周期回调:

public interface LifecycleProcessor extends Lifecycle {

    void onRefresh();

    void onClose();
}

如果我们想进一步控制bean的行为,例如控制bean初始化的顺序,可以考虑使用SmartLifecycle:

public interface SmartLifecycle extends Lifecycle, Phased {

    boolean isAutoStartup();

    //一定要使用callback.run(),否则DefaultLifecycleProcessor认为bean的stop方法一直没有结束(即使已经结束),超过30s后,可以通过下列方式更改等待时间
/*<bean id="lifecycleProcessor" 
 *class="org.springframework.context.support.DefaultLifecycleProcessor">
 *   <!-- timeout value in milliseconds -->
 *   <property name="timeoutPerShutdownPhase" value="10000"/>
 *</bean>
*/
    //DefaultLifecycleProcessor才会自己调用callback.run,与主程序异步执行
    void stop(Runnable callback);
}
public interface Phased {
    //返回一个Phase,作为调用start和stop方法的顺序
    int getPhase();
}

SmartLifecycle继承了Lifecycle,但是Lifecycle的stop方法将不在有意义,当isRunning()返回true时,将调用void stop(Runnable callback),启动时,Phase(即优先值)越小,越早调用start()方法,越晚调用stop()方法,如果不继承SmartLifecycle接口,只继承了Lifecycle接口,Phase默认为0.,我们使用上述接口定义了自己的bean的生命周期后,Phase相同的Bean一起启动和关闭,如果bean与bean之间有依赖关系,则忽略Phase的值

容器刷新或是启动时,DefaultLifecycleProcessor将检查每个SmartLifecycle对象的isAutoStartup()方法返回的布尔值,如果为true,并且isRunning返回为false,将直接调用其start方法,isRunning指在接收到start信号时,是否调用start方法,isAutoStartup()的作用在于设定容器自启动时,DefaultLifecycleProcessor是否传递start信号给本类

 

在基于web的ApplicationContext实现中,已有相应的实现来处理关闭web应用时恰当地关闭Spring IoC容器。

 如果你正在一个非web应用的环境下使用Spring IoC容器,想让容器优雅的关闭,并调用singleton的bean相应stop回调方法,你需要在JVM里注册一个“关闭钩子”(shutdown hook):

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public final class Boot {

    public static void main(final String[] args) throws Exception {
        ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

        // add a shutdown hook for the above context...
        ctx.registerShutdownHook();

        // app runs here...

        // main method exits, hook is called prior to the app shutting down...
    }
}

猜测registerShutdownHook()会收集所有的stop回调方法(isRunning返回为true),并将其注册为线程,在JVM关闭时,会执行这些线程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值