淺談Java生命週期管理機制_java

來源:互聯網
上載者:User

先扯再說

最近一直在研究某個國產開源的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。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.