原文地址:http://www.manongjc.com/article/432.html
最近一直在研究某個國產開源的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
?直接繼承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。