1. 程式人生 > >Spring容器級生命週期回撥——LifeCycle

Spring容器級生命週期回撥——LifeCycle

之前我們談了bean的生命週期中利用容器擴充套件點回調,來實現後置處理器以及bean的初始和銷燬回撥。但這些事件都是建立在容器已經成功啟動的基礎上,如果我們想在容器本身的生命週期(比如容器啟動、停止)事件上做一些工作怎麼辦呢?Spring提供了以下介面:

Lifecycle介面

任何Spring管理的物件都可以實現此介面。當ApplicationContext介面啟動和關閉時,它會呼叫本容器內所有的Lifecycle實現。
Lifecycle介面原型如下:

public interface Lifecycle {
    void start();
    void stop();
    boolean isRunning();
}

LifecycleProcessor介面

它繼承Lifcycle介面。同時,增加了2個方法,用於處理容器的refreshed和closed事件。
原型如下:

public interface LifecycleProcessor extends Lifecycle {
    void onRefresh();
    void onClose();
}

SmartLifecycle介面

若兩個物件有依賴關係(這種依賴不一定是一個bean引用另一個bean),希望某些bean先初始化,完成一些工作後,再初始化另一些bean。在此場景中,可以使用SmartLifecycle介面,該介面有個方法getPhase(),實現了父介面Phased,它返回一個int型數字,表明執行順序

:

public interface Phased {
    int getPhase();
}

SmartLifecycle介面原型如下:

public interface SmartLifecycle extends Lifecycle, Phased {
    boolean isAutoStartup();
    void stop(Runnable callback);
}

啟動時,最小的phase最先啟動,停止時相反。因此,若物件實現了SmartLifecycle介面,它的getPhase()方法返回Integer.MIN_VALUE,那麼該物件最先啟動,最後停止。若是getPhase()方法返回Integer.MAX_VALUE,那麼該方法最後啟動最先停止。關於phase的值,常規的並未實現SmartLifecycle介面的Lifecycle物件,其值預設為0。因此,負phase值表示要在常規Lifecycle物件之前啟動(在常規Lifecycyle物件之後停止),使用正值則恰恰相反。

SmartLifecycle中stop()方法有一個回撥引數。所有的實現在關閉處理完成後會呼叫回撥的run()方法,相當於開啟非同步關閉功能。

LifecycleProcessor介面在Spring中的預設實現是DefaultLifecycleProcessor類,該類會為每個回撥等待超時,預設超時是30秒。

可以重寫該類預設的引數,該類在容器內預設bean名稱是lifecycleProcessor。比如修改超時時間:

<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
    <!-- timeout value in milliseconds -->
    <property name="timeoutPerShutdownPhase" value="10000"/>
</bean>

SmartLifecycle的簡單使用

SmartLifecycle介面的實現類,簡單的說下每個方法的作用:

isAutoStartup()返回true時,Spring容器啟動時會去執行start()方法。
isRunning()返回true的時候,容器銷燬時會呼叫stop()方法。
getPhase()返回的是優先順序,如果有多個這樣的類可以指定不同的優先順序,讓其先後執行(銷燬的時候順序相反)。

@Component
public class CustomComponent implements SmartLifecycle {

    @Autowired
    private JdbcTemplate jdbcTemplate;
    private boolean hasData;

    @Override
    public boolean isRunning() {
        // TODO Auto-generated method stub
        return hasData;
    }

    @Override
    public void start() {
        System.out.println(">>>>>>>>>>>>>");
        String result = jdbcTemplate.queryForObject("select name from user ", String.class);
        System.out.println("start啟動服務載入的資料:" + result);
        hasData = StringUtils.isNotEmpty(result) ? true : false;
    }

    @Override
    public void stop() {
        // TODO Auto-generated method stub

    }

    @Override
    public int getPhase() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public boolean isAutoStartup() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public void stop(Runnable arg0) {
        if(hasData) {
            System.out.println("刪除表");
            jdbcTemplate.execute("drop table user");
        }
    }
}