浅谈Java生命周期管理机制
先扯再说
最近一直在研究某个国产开源的MySQL数据库中间件,拉下其最新版的代码到eclipse后,启动起来,然后做各种测试和代码追踪;用完想要关闭它时,拉出它的STOP类想要运行时,发现这个类里赫然只写以下几行代码,于是我感觉瞬间受到了很多伤害。
publicstaticvoidmain(String[]args){
System.out.println(newDate()+",servershutdown!");
}
这个中间件启动和运行的时候,开启了监听,启动着许多线程在跑着,并且有许多socket连接。但是并没有找到一个优雅的方式将其关闭。于是无奈之下,我只能去点eclipse的心碎小红点,强行停掉VM。
如果是一个架构良好,模块化清晰的软件,特别是Server类的软件,拥有一套生命周期管理机制是非常重要的。不仅可以管理各个模块的生命周期,也可以在启停整个软件的时候更优雅,不会漏掉任何资源。
生命周期机制简易实现
生命周期状态
一个模块的生命周期状态一般有以下几个:
新生->初始化中->初始化完成->启动中->启动完成->正在暂停->已经暂停->正在恢复->已经恢复->正在销毁->已经销毁
其中,任何一个状态之间的转化如果失败,那么就会进入另外一种状态:失败。
为此,可以用一个枚举类来枚举出这几个状态,如下所示:
publicenumLifecycleState{
NEW,//新生
INITIALIZING,INITIALIZED,//初始化
STARTING,STARTED,//启动
SUSPENDING,SUSPENDED,//暂停
RESUMING,RESUMED,//恢复
DESTROYING,DESTROYED,//销毁
FAILED;//失败
}
接口
生命周期中的各种行为规范,也需要一个接口来定义,如下所示:
publicinterfaceILifecycle{
/**
*初始化
*
*@throwsLifecycleException
*/
publicvoidinit()throwsLifecycleException;
/**
*启动
*
*@throwsLifecycleException
*/
publicvoidstart()throwsLifecycleException;
/**
*暂停
*
*@throwsLifecycleException
*/
publicvoidsuspend()throwsLifecycleException;
/**
*恢复
*
*@throwsLifecycleException
*/
publicvoidresume()throwsLifecycleException;
/**
*销毁
*
*@throwsLifecycleException
*/
publicvoiddestroy()throwsLifecycleException;
/**
*添加生命周期监听器
*
*@paramlistener
*/
publicvoidaddLifecycleListener(ILifecycleListenerlistener);
/**
*删除生命周期监听器
*
*@paramlistener
*/
publicvoidremoveLifecycleListener(ILifecycleListenerlistener);
}
发生生命周期状态转化时,可能需要触发对某类事件感兴趣的监听者,因此ILifeCycle也定义了两个方法可以添加和移除监听者。分别是:publicvoidaddLifecycleListener(ILifecycleListenerlistener);和publicvoidremoveLifecycleListener(ILifecycleListenerlistener);
监听者也由一个接口来定义其行为规范,如下所示:
publicinterfaceILifecycleListener{
/**
*对生命周期事件进行处理
*
*@paramevent生命周期事件
*/
publicvoidlifecycleEvent(LifecycleEventevent);
}
生命周期事件由LifecycleEvent来表示,如下所示:
publicfinalclassLifecycleEvent{
privateLifecycleStatestate;
publicLifecycleEvent(LifecycleStatestate){
this.state=state;
}
/**
*@returnthestate
*/
publicLifecycleStategetState(){
returnstate;
}
}
骨架实现
有了ILifeCycle接口以后,任何实现了这个接口的类将会被作为一个生命周期管理对象,这个类可以是一个socket监听服务,也可以代表一个特定的模块,等等。那我们是不是只要实现ILifeCycle就可以了?可以这么说,但考虑到各个生命周期管理对象在生命周期的各个阶段会有一些共同的行为,比如说:
设置自身的生命周期状态
检查状态的转换是否符合逻辑
通知监听者生命周期状态发生了变化
因此,提供一个抽象类AbstractLifeCycle,作为ILifeCycle的骨架实现是有重要意义的,这样避免了很多的重复代码,使得架构更加清晰。这个抽象类会实现ILifeCycle中定义的所有接口方法,并添加对应的抽象方法,供子类实现。AbstractLifeCycle可以这么实现:
publicabstractclassAbstractLifecycleimplementsILifecycle{
privateList<ILifecycleListener>listeners=newCopyOnWriteArrayList<ILifecycleListener>();
/**
*state代表当前生命周期状态
*/
privateLifecycleStatestate=LifecycleState.NEW;
/*
*@seeILifecycle#init()
*/
@Override
publicfinalsynchronizedvoidinit()throwsLifecycleException{
if(state!=LifecycleState.NEW){
return;
}
setStateAndFireEvent(LifecycleState.INITIALIZING);
try{
init0();
}catch(Throwablet){
setStateAndFireEvent(LifecycleState.FAILED);
if(tinstanceofLifecycleException){
throw(LifecycleException)t;
}else{
thrownewLifecycleException(formatString(
"Failedtoinitialize{0},ErrorMsg:{1}",toString(),t.getMessage()),t);
}
}
setStateAndFireEvent(LifecycleState.INITIALIZED);
}
protectedabstractvoidinit0()throwsLifecycleException;
/*
*@seeILifecycle#start()
*/
@Override
publicfinalsynchronizedvoidstart()throwsLifecycleException{
if(state==LifecycleState.NEW){
init();
}
if(state!=LifecycleState.INITIALIZED){
return;
}
setStateAndFireEvent(LifecycleState.STARTING);
try{
start0();
}catch(Throwablet){
setStateAndFireEvent(LifecycleState.FAILED);
if(tinstanceofLifecycleException){
throw(LifecycleException)t;
}else{
thrownewLifecycleException(formatString("Failedtostart{0},ErrorMsg:{1}",
toString(),t.getMessage()),t);
}
}
setStateAndFireEvent(LifecycleState.STARTED);
}
protectedabstractvoidstart0()throwsLifecycleException;
/*
*@seeILifecycle#suspend()
*/
@Override
publicfinalsynchronizedvoidsuspend()throwsLifecycleException{
if(state==LifecycleState.SUSPENDING||state==LifecycleState.SUSPENDED){
return;
}
if(state!=LifecycleState.STARTED){
return;
}
setStateAndFireEvent(LifecycleState.SUSPENDING);
try{
suspend0();
}catch(Throwablet){
setStateAndFireEvent(LifecycleState.FAILED);
if(tinstanceofLifecycleException){
throw(LifecycleException)t;
}else{
thrownewLifecycleException(formatString("Failedtosuspend{0},ErrorMsg:{1}",
toString(),t.getMessage()),t);
}
}
setStateAndFireEvent(LifecycleState.SUSPENDED);
}
protectedabstractvoidsuspend0()throwsLifecycleException;
/*
*@seeILifecycle#resume()
*/
@Override
publicfinalsynchronizedvoidresume()throwsLifecycleException{
if(state!=LifecycleState.SUSPENDED){
return;
}
setStateAndFireEvent(LifecycleState.RESUMING);
try{
resume0();
}catch(Throwablet){
setStateAndFireEvent(LifecycleState.FAILED);
if(tinstanceofLifecycleException){
throw(LifecycleException)t;
}else{
thrownewLifecycleException(formatString("Failedtoresume{0},ErrorMsg:{1}",
toString(),t.getMessage()),t);
}
}
setStateAndFireEvent(LifecycleState.RESUMED);
}
protectedabstractvoidresume0()throwsLifecycleException;
/*
*@seeILifecycle#destroy()
*/
@Override
publicfinalsynchronizedvoiddestroy()throwsLifecycleException{
if(state==LifecycleState.DESTROYING||state==LifecycleState.DESTROYED){
return;
}
setStateAndFireEvent(LifecycleState.DESTROYING);
try{
destroy0();
}catch(Throwablet){
setStateAndFireEvent(LifecycleState.FAILED);
if(tinstanceofLifecycleException){
throw(LifecycleException)t;
}else{
thrownewLifecycleException(formatString("Failedtodestroy{0},ErrorMsg:{1}",
toString(),t.getMessage()),t);
}
}
setStateAndFireEvent(LifecycleState.DESTROYED);
}
protectedabstractvoiddestroy0()throwsLifecycleException;
/*
*@see
*ILifecycle#addLifecycleListener(ILifecycleListener)
*/
@Override
publicvoidaddLifecycleListener(ILifecycleListenerlistener){
listeners.add(listener);
}
/*
*@see
*ILifecycle#removeLifecycleListener(ILifecycleListener)
*/
@Override
publicvoidremoveLifecycleListener(ILifecycleListenerlistener){
listeners.remove(listener);
}
privatevoidfireLifecycleEvent(LifecycleEventevent){
for(Iterator<ILifecycleListener>it=listeners.iterator();it.hasNext();){
ILifecycleListenerlistener=it.next();
listener.lifecycleEvent(event);
}
}
protectedsynchronizedLifecycleStategetState(){
returnstate;
}
privatesynchronizedvoidsetStateAndFireEvent(LifecycleStatenewState)throwsLifecycleException{
state=newState;
fireLifecycleEvent(newLifecycleEvent(state));
}
privateStringformatString(Stringpattern,Object...arguments){
returnMessageFormat.format(pattern,arguments);
}
/*
*@seejava.lang.Object#toString()
*/
@Override
publicStringtoString(){
returngetClass().getSimpleName();
}
}
可以看到,抽象类的骨架实现中做了几件生命周期管理中通用的事情,检查状态之间的转换是否合法(比如说start之前必须要init),设置内部状态,以及触发相应的监听者。
抽象类实现了ILifeCycle定义的方法后,又留出了相应的抽象方法供其子类实现,如上面的代码所示,其留出来的抽象方法有以下这些:
protectedabstractvoidinit0()throwsLifecycleException; protectedabstractvoidstart0()throwsLifecycleException; protectedabstractvoidsuspend0()throwsLifecycleException; protectedabstractvoidresume0()throwsLifecycleException; protectedabstractvoiddestroy0()throwsLifecycleException;
优雅的实现
到目前为止,我们已经定义了接口ILifeCycle,以及其骨架实现AbstractLifeCycle,并且增加了监听者机制。貌似我们可以开始写一个类来继承AbstractLifecycle,并重写其定义的抽象方法了,sofarsogood。
但在开始之前,我们还需要考虑另外几个问题,
我们的实现类是否对所有的抽象方法都感兴趣?
是否每个实现累都需要实现init0,start0,suspend0,resume0,destroy0?
是否有时候,我们的那些有生命的类或者模块并不支持暂停(suspend),恢复(resume)?
直接继承AbstractLifeCycle,就意味着必须实现其全部的抽象方法。
因此,我们还需要一个默认实现,DefaultLifeCycle,让它继承AbstractLifeCycle,并实现所有抽象方法,但它并不做任何实际的事情,donothing。只是让我们真正的实现类来继承这个默认的实现类,并重写感兴趣的方法。
于是,我们的DefaultLifeCycle就这么诞生了:
publicclassDefaultLifecycleextendsAbstractLifecycle{
/*
*@seeAbstractLifecycle#init0()
*/
@Override
protectedvoidinit0()throwsLifecycleException{
//donothing
}
/*
*@seeAbstractLifecycle#start0()
*/
@Override
protectedvoidstart0()throwsLifecycleException{
//donothing
}
/*
*@seeAbstractLifecycle#suspend0()
*/
@Override
protectedvoidsuspendInternal()throwsLifecycleException{
//donothing
}
/*
*@seeAbstractLifecycle#resume0()
*/
@Override
protectedvoidresume0()throwsLifecycleException{
//donothing
}
/*
*@seeAbstractLifecycle#destroy0()
*/
@Override
protectedvoiddestroy0()throwsLifecycleException{
//donothing
}
}
对于DefaultLifeCycle来说,donothing就是其职责。
因此接下来我们可以写一个自己的实现类,继承DefaultLifeCycle,并重写那些感兴趣的生命周期方法。
例如,我有一个类只需要在初始化,启动,和销毁时做一些任务,那么可以这么写:
importjava.io.IOException;
importjava.net.ServerSocket;
importjava.net.Socket;
publicclassSocketServerextendsDefaultLifecycle{
privateServerSocketacceptor=null;
privateintport=9527;
/*
*@seeDefaultLifecycle#init0()
*/
@Override
protectedvoidinit0()throwsLifecycleException{
try{
acceptor=newServerSocket(port);
}catch(IOExceptione){
thrownewLifecycleException(e);
}
}
/*
*@seeDefaultLifecycle#start0()
*/
@Override
protectedvoidstart0()throwsLifecycleException{
Socketsocket=null;
try{
socket=acceptor.accept();
//dosomethingwithsocket
}catch(IOExceptione){
thrownewLifecycleException(e);
}finally{
if(socket!=null){
try{
socket.close();
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
}
}
/*
*@seeDefaultLifecycle#destroy0()
*/
@Override
protectedvoiddestroy0()throwsLifecycleException{
if(acceptor!=null){
try{
acceptor.close();
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
}
}
这里的ServerSocket中,init0初始化socket监听,start0开始获取socket连接,destroy0销毁socket监听。
在这套生命周期管理机制下,我们将会很容易地对资源进行管理,不会发生资源未关闭的情况,架构和模块化更加清晰。
尾声
到这里为止,本文已经实现了一个简易的生命周期管理机制,并给出所有的实现代码。之后会将所有源代码放到github上。请关注本文的update。