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。

但在开始之前,我们还需要考虑另外几个问题,

  • 我们的实现类是否对所有的抽象方法都感兴趣?
  • 是否每个实现累都需要实现init0start0suspend0resume0destroy0?
  • 是否有时候,我们的那些有生命的类或者模块并不支持暂停(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。

时间: 2024-08-04 09:25:04

Java实现生命周期管理机制的相关文章

Android apk动态加载机制的研究(二):资源加载和activity生命周期管理

出处:http://blog.csdn.net/singwhatiwanna/article/details/23387079 (来自singwhatiwanna的csdn博客) 前言 为了更好地阅读本文,你需要先阅读Android apk动态加载机制的研究这篇文章,在此文中,博主分析了Android中apk的动态加载机制,并在文章的最后指出需要解决的两个复杂问题:资源的访问和activity生命周期的管理,而本文将会分析这两个复杂问题的解决方法.需要说明的一点是,我们不可能调起任何一个未安装的

tomcat系列分析之生命周期管理初始化动作

tomcat中有很多组件,要对这些组件进行生命周期的管理非常困难,tomcat中采用的是抽象出一个生命周期管理接口,然后所有的组件都实现该接口,当父组件启动时,同事负责将子组件启动起来,从而完成整tomcat的初始.启动.结束等动作. 来看下tomcat启动的过程,首先构造Bootstrap类,调用其中的init方法,完成类加载器的初始化,方便后面加载类使用,然后调用其中的load方法,实际上tomcat真正的启动动作是由Catalina类完成的.而这其中在BootStrap中调用Catalin

Tomcat7.0源码分析——生命周期管理

前言 从server.xml文件解析出来的各个对象都是容器,比如:Server.Service.Connector等.这些容器都具有新建.初始化完成.启动.停止.失败.销毁等状态.tomcat的实现提供了对这些容器的生命周期管理,本文将通过对Tomcat7.0的源码阅读,深入剖析这一过程. Tomcat生命周期类接口设计 我们先阅读图1,从中了解Tomcat涉及生命周期管理的主要类. 图1 Tomcat生命周期类接口设计 这里对图1中涉及的主要类作个简单介绍: Lifecycle:定义了容器生命

hibernate session缓存和java对象生命周期

一.java对象生命周期 1.在java中,使用new关键字,创建一个java对象,jvm就为这个对象分配一块内存空间.只要这个变量被引用,他就一直存在于内存中.如果没有被任何变量引用(包括间接引用),那么这个对象就会被垃圾回收器回收.下面用一段代码来解释: Customer c=new Customer(); Order o1=new Order(); Order 02=new Order(); o1.setCustomer(c); c.getOrders().add(o1); o1=null

构造函数的选择与服务生命周期管理

构造函数的选择与服务生命周期管理 ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationInstance和ImplementationFactory属性均为Null,那么ServiceProvider最终会利用其ImplementationType属性返回的真实类型选择一个适合的构造函数来创建最终的服务实例.我们知道服务服务的真实类型可以定义了多个构造函

k8s的Pod状态和生命周期管理

Pod状态和生命周期管理 一.什么是Pod? 二.Pod中如何管理多个容器? 三.使用Pod 四.Pod的持久性和终止 五.Pause容器 六.init容器 七.Pod的生命周期 (1)Pod phase(Pod的相位) (2)Pod的创建过程 (3)Pod的状态 (4)Pod存活性探测 (5)livenessProbe和readinessProbe使用场景 (6)Pod的重启策略 (7)Pod的生命 (8)livenessProbe解析 一.什么是Pod? Pod是kubernetes中你可以

Elastic 使用索引生命周期管理实现热温冷架构

Elastic: 使用索引生命周期管理实现热温冷架构 索引生命周期管理 (ILM) 是在 Elasticsearch 6.6(公测版)首次引入并在 6.7 版正式推出的一项功能.ILM 是 Elasticsearch 的一部分,主要用来帮助您管理索引. 在本篇博客中,我们将探讨如何使用 ILM 实现热温冷架构.热温冷架构常用于日志或指标类的时序数据.例如,假设正在使用 Elasticsearch 聚合来自多个系统的日志文件.今天的日志正在频繁地被索引,且本周的日志搜索量最大(热).上周的日志可能

Siemens PLM TeamCenter 9.1生命周期管理软件

Siemens PLM TeamCenter 9.1生命周期管理软件Teamcenter 在构建时充分考虑了可扩展性. 无论是需要小规模部署来支持单个站点的小型团队,还是拥有遍布全球的众多站点以及复杂供应链的大型企业,或者介于其间的任何公司,Teamcenter 灵活的体系架构都能满足您当前的业务需求,并能随着贵公司的增长而继续保持出色表现. 下载内容包括: Siemens PLM TeamCenter 9.1 32和64位 为多国语言版本 Disc3 和 Disc4安装包 Teamcenter

java类生命周期详细解析

(一)详解java类的生命周期 引言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前国内java方面的教材大多只是告诉你“怎样做”,但至于“为什么这样做”却不多说,所以造成大家在基础和原理方面的知识比较匮乏,所以笔者今天就斗胆来讲一下这个问题,权当抛砖引玉,希望对在这个问题上有疑惑的朋友有所帮助,文中有说的不对的地方,也希望各路高手前来指正. 首先来了解一下jvm(java虚拟机)