Container容器-tomcat6.x源码阅读

2013-09-21

容器是tomcat的基础,tomcat通过容器来管理和维护tomcat组件,最外层的容器是Server,最内层的容器是Wrapper,容器提供了一些基础的功能,例如添加父容器,子容器,共享数据,数据隔离等。

Container
Container是tomcat中的容器接口,定义了容器所具有的方法和tomcat中容器的规范。容器接口提供了操作容器的方法,例如设置父容器和添加子容器,查找容器,添加监听容器事件的监听器,是invoke(Request, Response)处理HTTP协议请求的方法。

ContainerBase
ContainerBase是Container接口的基本实现,是个抽象类,在类中提供了Container大多数方法的实现,把一些容器公共实现抽象到ContainerBase实现。ContainerBase的功能是:实现了Container接口的大多数方法,把子类所需要实现的共同方法在基类中实现,避免在子类中重复编码,子类通过继承ContainerBase类来完成。

LifecycleSupport
ContainerBase抽象类中的属性,Lifecycle接口实现类,功能是负责管理注册在容器上面的LifecycleEvent监听类,监听容器的生命周期变更,集中管理监听器。

listeners
ContainerBase的属性,容器监听器数组,用户监听容器本身事件,监听的是ContainerEvent事件,与LifecycleEvent不同。

Loader
ContainerBase的属性,tomcat自己封装的类加载器,针对webapp安全的类加载,管理webapp的类加载,在java的类加载器体系中,不同类加载器加载的类实例是不能同时访问的。

Manager
ContainerBase的属性,Manager是用来管理在容器上面的Session池,负责Session的生命周期,从生成到销毁,Manager是一个管理Session池的一个方法集合接口。

cluster : Cluster
ContainerBase的属性,跟集群有关。

pipeline : Pipeline
ContainerBase的属性,很重要,是Valve链,功能是负责管理Valve,也是请求信息传递链,最终目的是ServletWrapper中。pipeline 决定Valve的顺序,控制请求信息,是容器间传递请求信息的桥梁。

support : PropertyChangeSupport
ContainerBase的属性,容器属性更新监听器集中管理,跟LifecycleSupport功能一样。

backgroundProcess()
Container接口方法,Container定义该方法的目的是启用一个后台进程来处理一些逻辑,比如重新加载配置,判断Session失效等。

ContainerBackgroundProcessor
ContainerBase基本容器的内部类,实现了Runnable接口,具体作用是作为一个后台程序定时触发backgroundProcess()后台处理方法。

    /**
     * Private thread class to invoke the backgroundProcess method of this
     * container and its children after a fixed delay.
     */
    protected class ContainerBackgroundProcessor implements Runnable {

        public void run() {
            while (!threadDone) {
                try {
                    Thread.sleep(backgroundProcessorDelay * 1000L);//睡眠
                } catch (InterruptedException e) {
                    ;
                }
                if (!threadDone) {
                    //取类加载器,确保容器和子容器在同一个类加载器中
                    Container parent = (Container) getMappingObject();
                    ClassLoader cl = Thread.currentThread()
                            .getContextClassLoader();
                    if (parent.getLoader() != null) {
                        cl = parent.getLoader().getClassLoader();
                    }
                    processChildren(parent, cl);//调用容器的backgroundProcess()方法
                }
            }
        }

        /**
         *  处理子容器
         * @param container
         * @param cl
         */
        protected void processChildren(Container container, ClassLoader cl) {
            try {
                if (container.getLoader() != null) {
                    Thread.currentThread().setContextClassLoader(
                            container.getLoader().getClassLoader());
                }
                container.backgroundProcess();//调用后台处理方法
            } catch (Throwable t) {
                log.error("Exception invoking periodic operation: ", t);
            } finally {
                Thread.currentThread().setContextClassLoader(cl);
            }
            Container[] children = container.findChildren();
            for (int i = 0; i < children.length; i++) {
                if (children[i].getBackgroundProcessorDelay() <= 0) {
                    processChildren(children[i], cl);//处理子容器
                }
            }
        }

    }

init()
负责容器的初始化工作,主要有一下几步,

  • 注册到MBeanServer
  • 标记已经初始化
    /**
     * Init method, part of the MBean lifecycle. If the container was added via
     * JMX, it'll register itself with the parent, using the ObjectName
     * conventions to locate the parent.
     * 
     * If the container was added directly and it doesn't have an ObjectName,
     * it'll create a name and register itself with the JMX console. On
     * destroy(), the object will unregister.
     * 
     * @throws Exception
     */
    public void init() throws Exception {

        if (this.getParent() == null) {
            // "Life" update
            ObjectName parentName = getParentName();

            // log.info("Register " + parentName );
            if (parentName != null && mserver.isRegistered(parentName)) {
                mserver.invoke(parentName, "addChild", new Object[] { this },
                        new String[] { "org.apache.catalina.Container" });
            }
        }
        initialized = true;
    }

start()
负责容器的启动工作,主要有以下几步,主要启动添加在容器上面的组件。

  • 判断是否已经启动
  • 触发BEFORE_START_EVENT事件,标记已经启动
  • 启动类加载器loader,日志记录器logger,session管理器manager,集群节点cluster,权限管理器realm,目录资源服务resources
  • 启动子容器
  • 启动Valve链pipeline
  • 触发START_EVENT事件
  • 启动后台任务处理进程
  • 触发AFTER_START_EVENT事件
    /**
     * Prepare for active use of the public methods of this Component.
     * 预启动的公有方法
     * @exception LifecycleException
     *                if this component detects a fatal error that prevents it
     *                from being started
     */
    public synchronized void start() throws LifecycleException {

        // Validate and update our current component state
        if (started) {
            if (log.isInfoEnabled())
                log.info(sm
                        .getString("containerBase.alreadyStarted", logName()));
            return;
        }

        // Notify our interested LifecycleListeners
        //开始启动事件监听
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);

        started = true;

        // Start our subordinate components, if any
        if ((loader != null) && (loader instanceof Lifecycle))
            ((Lifecycle) loader).start();//加载器启动
        logger = null;
        getLogger();
        if ((logger != null) && (logger instanceof Lifecycle))
            ((Lifecycle) logger).start();
        if ((manager != null) && (manager instanceof Lifecycle))
            ((Lifecycle) manager).start();//管理器启动
        if ((cluster != null) && (cluster instanceof Lifecycle))
            ((Lifecycle) cluster).start();//集群从节点启动
        if ((realm != null) && (realm instanceof Lifecycle))
            ((Lifecycle) realm).start();
        if ((resources != null) && (resources instanceof Lifecycle))
            ((Lifecycle) resources).start();//资源启动

        // Start our child containers, if any
        Container children[] = findChildren();
        for (int i = 0; i < children.length; i++) {
            if (children[i] instanceof Lifecycle)
                ((Lifecycle) children[i]).start();//启动子容器
        }

        // Start the Valves in our pipeline (including the basic), if any
        if (pipeline instanceof Lifecycle)
            ((Lifecycle) pipeline).start();//监听pipe功能

        // Notify our interested LifecycleListeners
        //正在启动事件通知
        lifecycle.fireLifecycleEvent(START_EVENT, null);

        // Start our thread
        threadStart();//启动线程

        // Notify our interested LifecycleListeners
        //完成启动事件通知
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);

    }

stop()
负责停止容器,所做的工作就是按照start()方法中组件启动的顺序逆序停止组件。

    /**
     * Gracefully shut down active use of the public methods of this Component.
     * 优雅关闭容器的公有方法
     * @exception LifecycleException
     *                if this component detects a fatal error that needs to be
     *                reported
     */
    public synchronized void stop() throws LifecycleException {

        // Validate and update our current component state
        if (!started) {
            if (log.isInfoEnabled())
                log.info(sm.getString("containerBase.notStarted", logName()));
            return;
        }

        // Notify our interested LifecycleListeners
        //准备停止容器事件通知
        lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);

        // Stop our thread
        threadStop();//停止线程

        // Notify our interested LifecycleListeners
        //停止容器事件通知
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;

        // Stop the Valves in our pipeline (including the basic), if any
        if (pipeline instanceof Lifecycle) {
            ((Lifecycle) pipeline).stop();//pipe停止
        }

        // Stop our child containers, if any
        Container children[] = findChildren();
        for (int i = 0; i < children.length; i++) {
            if (children[i] instanceof Lifecycle)
                ((Lifecycle) children[i]).stop();//子容器停止
        }
        // Remove children - so next start can work
        children = findChildren();
        for (int i = 0; i < children.length; i++) {
            removeChild(children[i]);//移除子容器
        }

        // Stop our subordinate components, if any
        if ((resources != null) && (resources instanceof Lifecycle)) {
            ((Lifecycle) resources).stop();//资源停止
        }
        if ((realm != null) && (realm instanceof Lifecycle)) {
            ((Lifecycle) realm).stop();
        }
        if ((cluster != null) && (cluster instanceof Lifecycle)) {
            ((Lifecycle) cluster).stop();//集群子节点停止
        }
        if ((manager != null) && (manager instanceof Lifecycle)) {
            ((Lifecycle) manager).stop();//管理器停止
        }
        if ((logger != null) && (logger instanceof Lifecycle)) {
            ((Lifecycle) logger).stop();
        }
        if ((loader != null) && (loader instanceof Lifecycle)) {
            ((Lifecycle) loader).stop();
        }

        // Notify our interested LifecycleListeners
        //完成停止容器事件通知
        lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);

    }

destroy()
负责销毁容器,主要工作是注销MBeanServer,移除父容器引用,移除容器

    /**
     * 停止容器
     * @throws Exception
     */
    public void destroy() throws Exception {
        if (started) {
            stop();
        }
        initialized = false;

        // unregister this component
        if (oname != null) {
            try {
                if (controller == oname) {
                    Registry.getRegistry(null, null).unregisterComponent(oname);
                    if (log.isDebugEnabled())
                        log.debug("unregistering " + oname);
                }
            } catch (Throwable t) {
                log.error("Error unregistering ", t);
            }
        }

        if (parent != null) {
            parent.removeChild(this);
        }

        // Stop our child containers, if any
        Container children[] = findChildren();
        for (int i = 0; i < children.length; i++) {
            removeChild(children[i]);
        }

    }

threadStart()
负责启动容器的后台任务程序。

    /**
     * Start the background thread that will periodically check for session
     * timeouts.
     * 启动后台线程并定期检查session失效
     */
    protected void threadStart() {

        if (thread != null)
            return;
        if (backgroundProcessorDelay <= 0)
            return;

        threadDone = false;
        String threadName = "ContainerBackgroundProcessor[" + toString() + "]";
        thread = new Thread(new ContainerBackgroundProcessor(), threadName);
        thread.setDaemon(true);//后台程序
        thread.start();

    }

threadStop()
负责停止后台进程运行。

    /**
     * Stop the background thread that is periodically checking for session
     * timeouts.
     * 停止线程
     */
    protected void threadStop() {

        if (thread == null)
            return;

        threadDone = true;
        thread.interrupt();//打断方式停止
        try {
            thread.join();
        } catch (InterruptedException e) {
            ;
        }

        thread = null;

    }

从上面的组件和方法可以看出,容器所需完成的功能或者说是所具备的功能有:

  • 设置父容器,添加管理子容器
  • 管理Session
  • 权限管理
  • 后台任务处理
  • 生命周期事件监听
  • 属性变更事件监听
  • Valve链,过滤请求和响应信息

说好的坚持,总是断断续续

你可能感兴趣的:(Container容器-tomcat6.x源码阅读)