1. 程式人生 > >Spring的Bean生命週期內的callback方法和Spring容器啟動關閉時的callback方法

Spring的Bean生命週期內的callback方法和Spring容器啟動關閉時的callback方法

通過Spring管理的bean,在其生命週期內可以配置被Spring呼叫的callback方法一般有兩種:通過實現Spring提供的特點介面和通過配置callback方法.(如果bean是prototype的話,由於其銷燬不被Spring管理,其銷燬方法不會被呼叫)

1,通過實現Spring提供的特點介面:通過實現InitializingBean介面,Spring容器會在初始化bean的時候呼叫該bean的afterPropertiesSet方法,通過實現DisposableBean介面,Spring容器會在銷燬bean的時候呼叫該bean的destroy()方法.

例:

public class InitDisposeBean implements InitializingBean,DisposableBean {
    protected static final Log log = LogFactory.getLog(InitDisposeBean.class);
    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("afterPropertiesSet");
       
    }
    @Override
    public void destroy() throws Exception {
        log.info("destroy");       
    }
    public void test() {
        log.info("test");       
    }
}

<bean id="InitDisposeBean" class="com.test.spring.lifecycle.InitDisposeBean" />
2,通過配置檔案指定callback方法:
public class InitDisposeCfgBean {
    protected static final Log log = LogFactory.getLog(InitDisposeCfgBean.class);
    public void init()  {
        log.info("init"); 
    } 
    public void cleanup() {
        log.info("cleanup");       
    } 
    public void test() {
        log.info("test");       
    }
}

<bean id="InitDisposeCfgBean" class="com.test.spring.lifecycle.InitDisposeCfgBean" init-method="init" destroy-method="cleanup"/>
通常推薦使用第二種方法,這種做法更符合IoC的思想,並且不實現Spring的介面,程式碼獨立於Spring.如果實現InitializingBean的同時指定init-method,InitializingBean的afterPropertiesSet方法會在init-method指定的方法之前呼叫.(沒有理由同時這麼做...)

Spring還提供一種在最上層定義初始化和銷燬方法,只要保持Bean的初始化和銷燬方法按照一定的命名規範定義這些方法,就不需要為每一個bean單獨指定初始化和銷燬方法了.對於不存在這些方法的bean,Spring初始化這些bean的時候就忽略這種配置.

<beans default-init-method="init" default-destroy-method="cleanUp">

    <bean ....>

</beans>
Spring容器啟動和關閉的時候,配置對bean的callback方法通常用來配置後臺程式,在啟動後一直執行(如對MQ進行輪詢等等),通過實現Spring提供的介面:Lifecycle,phased或者SmartLifecycle來實現(其中SmartLifecycle繼承了Lifecycle和phased).

在Spring啟動和關閉時被呼叫的callback方法:

例:

public class LfCycleBean1 implements SmartLifecycle{
    protected static final Log log = LogFactory.getLog(LfCycleBean1.class);
    private boolean isRunning = false;
    @Override
    public boolean isAutoStartup() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public void stop(Runnable arg0) {
        arg0.run();
        isRunning = false;
        log.info("stop Runnable");   
    }

    @Override
    public boolean isRunning() {
        // TODO Auto-generated method stub
        return isRunning;
    }
    @Override
    public void start() {
        isRunning = true;
        log.info("start ");    
    }
    @Override
    public void stop() {
        isRunning = false;
        log.info("stop");   
    }
    @Override
    public int getPhase() {      
        return -1;
    }
}

<bean id="LfCycleBean1" class="com.test.spring.lifecycle.LfCycleBean1" />
isAutoStartup返回的值決定是否在Spring啟動的時候執行start方法,ture的話則執行.
isRunning返回的值決定是否在Spring關閉的時候執行stop(Runnable arg0)方法,ture的話則執行.
getPhase返回的值決定啟動的順序,值越小越先啟動,越後關閉,用於調整在有多個這樣的bean的時候,這些bean之間啟動的優先順序.
*需要設定ctx.registerShutdownHook(),Spring容器關閉的時候才會呼叫stop方法.
        AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("conf/lfCycleAppcontext.xml");    
        ctx.registerShutdownHook();