Java實現生命周期管理機制
先扯再說
最近一直在研究某個國產開源的MySQL數據庫中間件,拉下其最新版的代碼到eclipse后,啟動起來,然后做各種測試和代碼追蹤;用完想要關閉它時,拉出它的STOP類想要運行時,發現這個類里赫然只寫以下幾行代碼,于是我感覺瞬間受到了很多傷害。
public static void main(String[] args) {
System.out.println(new Date() + ",server shutdown!");
} 這個中間件啟動和運行的時候,開啟了監聽,啟動著許多線程在跑著,并且有許多socket連接。但是并沒有找到一個優雅的方式將其關閉。于是無奈之下,我只能去點eclipse的心碎小紅點,強行停掉VM。
如果是一個架構良好,模塊化清晰的軟件,特別是Server類的軟件,擁有一套生命周期管理機制是非常重要的。不僅可以管理各個模塊的生命周期,也可以在啟停整個軟件的時候更優雅,不會漏掉任何資源。
生命周期機制簡易實現
生命周期狀態
一個模塊的生命周期狀態一般有以下幾個:
新生 -> 初始化中 -> 初始化完成 -> 啟動中 -> 啟動完成 -> 正在暫停 -> 已經暫停 -> 正在恢復 -> 已經恢復 -> 正在銷毀 -> 已經銷毀
其中,任何一個狀態之間的轉化如果失敗,那么就會進入另外一種狀態:失敗。
為此,可以用一個枚舉類來枚舉出這幾個狀態,如下所示:
public enum LifecycleState {
NEW, //新生
INITIALIZING, INITIALIZED, //初始化
STARTING, STARTED, //啟動
SUSPENDING, SUSPENDED, //暫停
RESUMING, RESUMED,//恢復
DESTROYING, DESTROYED,//銷毀
FAILED;//失敗
} 接口
生命周期中的各種行為規范,也需要一個接口來定義,如下所示:
public interface ILifecycle {
/**
* 初始化
*
* @throws LifecycleException
*/
public void init() throws LifecycleException;
/**
* 啟動
*
* @throws LifecycleException
*/
public void start() throws LifecycleException;
/**
* 暫停
*
* @throws LifecycleException
*/
public void suspend() throws LifecycleException;
/**
* 恢復
*
* @throws LifecycleException
*/
public void resume() throws LifecycleException;
/**
* 銷毀
*
* @throws LifecycleException
*/
public void destroy() throws LifecycleException;
/**
* 添加生命周期監聽器
*
* @param listener
*/
public void addLifecycleListener(ILifecycleListener listener);
/**
* 刪除生命周期監聽器
*
* @param listener
*/
public void removeLifecycleListener(ILifecycleListener listener);
} 發生生命周期狀態轉化時,可能需要觸發對某類事件感興趣的監聽者,因此ILifeCycle也定義了兩個方法可以添加和移除監聽者。分別是:public void addLifecycleListener(ILifecycleListener listener);和 public void removeLifecycleListener(ILifecycleListener listener);
監聽者也由一個接口來定義其行為規范,如下所示:
public interface ILifecycleListener {
/**
* 對生命周期事件進行處理
*
* @param event 生命周期事件
*/
public void lifecycleEvent(LifecycleEvent event);
} 生命周期事件由LifecycleEvent來表示,如下所示:
public final class LifecycleEvent {
private LifecycleState state;
public LifecycleEvent(LifecycleState state) {
this.state = state;
}
/**
* @return the state
*/
public LifecycleState getState() {
return state;
}
} 骨架實現
有了ILifeCycle接口以后,任何實現了這個接口的類將會被作為一個生命周期管理對象,這個類可以是一個socket監聽服務,也可以代表一個特定的模塊,等等。那我們是不是只要實現ILifeCycle就可以了? 可以這么說,但考慮到各個生命周期管理對象在生命周期的各個階段會有一些共同的行為,比如說:
-
設置自身的生命周期狀態
-
檢查狀態的轉換是否符合邏輯
-
通知監聽者生命周期狀態發生了變化
因此,提供一個抽象類AbstractLifeCycle,作為ILifeCycle的骨架實現是有重要意義的,這樣避免了很多的重復代碼,使得架構更加清晰。這個抽象類會實現ILifeCycle中定義的所有接口方法,并添加對應的抽象方法,供子類實現。AbstractLifeCycle可以這么實現:
public abstract class AbstractLifecycle implements ILifecycle {
private List<ILifecycleListener> listeners = new CopyOnWriteArrayList<ILifecycleListener>();
/**
* state 代表當前生命周期狀態
*/
private LifecycleState state = LifecycleState.NEW;
/*
* @see ILifecycle#init()
*/
@Override
public final synchronized void init() throws LifecycleException {
if (state != LifecycleState.NEW) {
return;
}
setStateAndFireEvent(LifecycleState.INITIALIZING);
try {
init0();
} catch (Throwable t) {
setStateAndFireEvent(LifecycleState.FAILED);
if (t instanceof LifecycleException) {
throw (LifecycleException) t;
} else {
throw new LifecycleException(formatString(
"Failed to initialize {0}, Error Msg: {1}", toString(), t.getMessage()), t);
}
}
setStateAndFireEvent(LifecycleState.INITIALIZED);
}
protected abstract void init0() throws LifecycleException;
/*
* @see ILifecycle#start()
*/
@Override
public final synchronized void start() throws LifecycleException {
if (state == LifecycleState.NEW) {
init();
}
if (state != LifecycleState.INITIALIZED) {
return;
}
setStateAndFireEvent(LifecycleState.STARTING);
try {
start0();
} catch (Throwable t) {
setStateAndFireEvent(LifecycleState.FAILED);
if (t instanceof LifecycleException) {
throw (LifecycleException) t;
} else {
throw new LifecycleException(formatString("Failed to start {0}, Error Msg: {1}",
toString(), t.getMessage()), t);
}
}
setStateAndFireEvent(LifecycleState.STARTED);
}
protected abstract void start0() throws LifecycleException;
/*
* @see ILifecycle#suspend()
*/
@Override
public final synchronized void suspend() throws LifecycleException {
if (state == LifecycleState.SUSPENDING || state == LifecycleState.SUSPENDED) {
return;
}
if (state != LifecycleState.STARTED) {
return;
}
setStateAndFireEvent(LifecycleState.SUSPENDING);
try {
suspend0();
} catch (Throwable t) {
setStateAndFireEvent(LifecycleState.FAILED);
if (t instanceof LifecycleException) {
throw (LifecycleException) t;
} else {
throw new LifecycleException(formatString("Failed to suspend {0}, Error Msg: {1}",
toString(), t.getMessage()), t);
}
}
setStateAndFireEvent(LifecycleState.SUSPENDED);
}
protected abstract void suspend0() throws LifecycleException;
/*
* @see ILifecycle#resume()
*/
@Override
public final synchronized void resume() throws LifecycleException {
if (state != LifecycleState.SUSPENDED) {
return;
}
setStateAndFireEvent(LifecycleState.RESUMING);
try {
resume0();
} catch (Throwable t) {
setStateAndFireEvent(LifecycleState.FAILED);
if (t instanceof LifecycleException) {
throw (LifecycleException) t;
} else {
throw new LifecycleException(formatString("Failed to resume {0}, Error Msg: {1}",
toString(), t.getMessage()), t);
}
}
setStateAndFireEvent(LifecycleState.RESUMED);
}
protected abstract void resume0() throws LifecycleException;
/*
* @see ILifecycle#destroy()
*/
@Override
public final synchronized void destroy() throws LifecycleException {
if (state == LifecycleState.DESTROYING || state == LifecycleState.DESTROYED) {
return;
}
setStateAndFireEvent(LifecycleState.DESTROYING);
try {
destroy0();
} catch (Throwable t) {
setStateAndFireEvent(LifecycleState.FAILED);
if (t instanceof LifecycleException) {
throw (LifecycleException) t;
} else {
throw new LifecycleException(formatString("Failed to destroy {0}, Error Msg: {1}",
toString(), t.getMessage()), t);
}
}
setStateAndFireEvent(LifecycleState.DESTROYED);
}
protected abstract void destroy0() throws LifecycleException;
/*
* @see
* ILifecycle#addLifecycleListener(ILifecycleListener)
*/
@Override
public void addLifecycleListener(ILifecycleListener listener) {
listeners.add(listener);
}
/*
* @see
* ILifecycle#removeLifecycleListener(ILifecycleListener)
*/
@Override
public void removeLifecycleListener(ILifecycleListener listener) {
listeners.remove(listener);
}
private void fireLifecycleEvent(LifecycleEvent event) {
for (Iterator<ILifecycleListener> it = listeners.iterator(); it.hasNext();) {
ILifecycleListener listener = it.next();
listener.lifecycleEvent(event);
}
}
protected synchronized LifecycleState getState() {
return state;
}
private synchronized void setStateAndFireEvent(LifecycleState newState) throws LifecycleException {
state = newState;
fireLifecycleEvent(new LifecycleEvent(state));
}
private String formatString(String pattern, Object... arguments) {
return MessageFormat.format(pattern, arguments);
}
/*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return getClass().getSimpleName();
}
} 可以看到,抽象類的骨架實現中做了幾件生命周期管理中通用的事情,檢查狀態之間的轉換是否合法(比如說start之前必須要init),設置內部狀態,以及觸發相應的監聽者。
抽象類實現了ILifeCycle定義的方法后,又留出了相應的抽象方法供其子類實現,如上面的代碼所示,其留出來的抽象方法有以下這些:
protected abstract void init0() throws LifecycleException; protected abstract void start0() throws LifecycleException; protected abstract void suspend0() throws LifecycleException; protected abstract void resume0() throws LifecycleException; protected abstract void destroy0() throws LifecycleException;
優雅的實現
到目前為止,我們已經定義了接口ILifeCycle,以及其骨架實現AbstractLifeCycle,并且增加了監聽者機制。貌似我們可以開始寫一個類來繼承AbstractLifecycle,并重寫其定義的抽象方法了,so far so good。
但在開始之前,我們還需要考慮另外幾個問題,
-
我們的實現類是否對所有的抽象方法都感興趣?
-
是否每個實現累都需要實現
init0,start0,suspend0,resume0,destroy0? -
是否有時候,我們的那些有生命的類或者模塊并不支持暫停(suspend),恢復(resume)?
直接繼承AbstractLifeCycle,就意味著必須實現其全部的抽象方法。
因此,我們還需要一個默認實現,DefaultLifeCycle,讓它繼承AbstractLifeCycle,并實現所有抽象方法,但它并不做任何實際的事情, do nothing。只是讓我們真正的實現類來繼承這個默認的實現類,并重寫感興趣的方法。
于是,我們的DefaultLifeCycle就這么誕生了:
public class DefaultLifecycle extends AbstractLifecycle {
/*
* @see AbstractLifecycle#init0()
*/
@Override
protected void init0() throws LifecycleException {
// do nothing
}
/*
* @see AbstractLifecycle#start0()
*/
@Override
protected void start0() throws LifecycleException {
// do nothing
}
/*
* @see AbstractLifecycle#suspend0()
*/
@Override
protected void suspendInternal() throws LifecycleException {
// do nothing
}
/*
* @see AbstractLifecycle#resume0()
*/
@Override
protected void resume0() throws LifecycleException {
// do nothing
}
/*
* @see AbstractLifecycle#destroy0()
*/
@Override
protected void destroy0() throws LifecycleException {
// do nothing
}
} 對于DefaultLifeCycle來說,do nothing就是其職責。
因此接下來我們可以寫一個自己的實現類,繼承DefaultLifeCycle,并重寫那些感興趣的生命周期方法。
例如,我有一個類只需要在初始化,啟動,和銷毀時做一些任務,那么可以這么寫:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketServer extends DefaultLifecycle {
private ServerSocket acceptor = null;
private int port = 9527;
/*
* @see DefaultLifecycle#init0()
*/
@Override
protected void init0() throws LifecycleException {
try {
acceptor = new ServerSocket(port);
} catch (IOException e) {
throw new LifecycleException(e);
}
}
/*
* @see DefaultLifecycle#start0()
*/
@Override
protected void start0() throws LifecycleException {
Socket socket = null;
try {
socket = acceptor.accept();
//do something with socket
} catch (IOException e) {
throw new LifecycleException(e);
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/*
* @see DefaultLifecycle#destroy0()
*/
@Override
protected void destroy0() throws LifecycleException {
if (acceptor != null) {
try {
acceptor.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} 這里的ServerSocket中,init0初始化socket監聽,start0開始獲取socket連接, destroy0銷毀socket監聽。
在這套生命周期管理機制下,我們將會很容易地對資源進行管理,不會發生資源未關閉的情況,架構和模塊化更加清晰。
尾聲
到這里為止,本文已經實現了一個簡易的生命周期管理機制,并給出所有的實現代碼。之后會將所有源代碼放到github上。請關注本文的update。