Tomcat源码分析之Server与Lifecycle的设计与实现

最近看Tomcat的源码的节奏还算是挺紧凑的,给人的感觉,tomcat的代码相对以前读的jetty的代码显得更有条理一些。。。当然这也是有可能是因为自己看的jetty的版本是比较老的,而看的Tomcat的代码却是比较新的Tomcat8的代码。。。。

好了闲话不多说了。。。

先来说说LifeCycle的概念。。。

这个在jetty中也有,组要是用于维护一个组件的生命周期,例如start,stop啥的。。。

另外对于有lifecycle概念的组件,一般也都还有listener的概念,当组件的状态发生改变的时候,可以有listener进行响应。。。

好啦先来看看最上层的LifeCycle接口的定义吧:

//生命周期的接口定义
public interface Lifecycle {

	
	//下面定义了一些基本的状态
    public static final String BEFORE_INIT_EVENT = "before_init";


    /**
     * The LifecycleEvent type for the "component after init" event.
     */
    public static final String AFTER_INIT_EVENT = "after_init";


    /**
     * The LifecycleEvent type for the "component start" event.
     */
    public static final String START_EVENT = "start";


    /**
     * The LifecycleEvent type for the "component before start" event.
     */
    public static final String BEFORE_START_EVENT = "before_start";


    /**
     * The LifecycleEvent type for the "component after start" event.
     */
    public static final String AFTER_START_EVENT = "after_start";


    /**
     * The LifecycleEvent type for the "component stop" event.
     */
    public static final String STOP_EVENT = "stop";


    /**
     * The LifecycleEvent type for the "component before stop" event.
     */
    public static final String BEFORE_STOP_EVENT = "before_stop";


    /**
     * The LifecycleEvent type for the "component after stop" event.
     */
    public static final String AFTER_STOP_EVENT = "after_stop";


    /**
     * The LifecycleEvent type for the "component after destroy" event.
     */
    public static final String AFTER_DESTROY_EVENT = "after_destroy";


    /**
     * The LifecycleEvent type for the "component before destroy" event.
     */
    public static final String BEFORE_DESTROY_EVENT = "before_destroy";


    /**
     * The LifecycleEvent type for the "periodic" event.
     */
    public static final String PERIODIC_EVENT = "periodic";


  
    public static final String CONFIGURE_START_EVENT = "configure_start";

    public static final String CONFIGURE_STOP_EVENT = "configure_stop";


    // --------------------------------------------------------- Public Methods


    /**
     * Add a LifecycleEvent listener to this component.
     *
     * @param listener The listener to add
     */
    //添加一个监听器
    public void addLifecycleListener(LifecycleListener listener);


    /**
     * Get the life cycle listeners associated with this life cycle. If this
     * component has no listeners registered, a zero-length array is returned.
     */
    //返回所有的监听器
    public LifecycleListener[] findLifecycleListeners();


    /**
     * Remove a LifecycleEvent listener from this component.
     *
     * @param listener The listener to remove
     */
    //移除一个监听器
    public void removeLifecycleListener(LifecycleListener listener);


  
    //初始化
    public void init() throws LifecycleException;

    //启动
    public void start() throws LifecycleException;


    //停止
    public void stop() throws LifecycleException;

    /**
     * Prepare to discard the object. The following {@link LifecycleEvent}s will
     * be fired in the following order:
     * <ol>
     *   <li>DESTROY_EVENT: On the successful completion of component
     *                      destruction.</li>
     * </ol>
     *
     * @exception LifecycleException if this component detects a fatal error
     *  that prevents this component from being used
     */
    //销毁
    public void destroy() throws LifecycleException;


    /**
     * Obtain the current state of the source component.
     *
     * @return The current state of the source component.
     */
    //返回当前的生命周期状态
    public LifecycleState getState();


    /**
     * Obtain a textual representation of the current component state. Useful
     * for JMX.
     */
    //返回状态的名字
    public String getStateName();
}

还是比较简单的吧,先是一些基本的状态和事件的定义,然后接下来是一些基本的操作,例如添加listener,移除listener,启动,停止什么的。。都还算比较的常规。。。


接下来是LifeCycle的抽象层,LifecycleBase。。。

这里就不具体的体贴出它的实现代码了,。。。LifecycleBase直接继承自LifeCycle接口,这里主要是实现了中间添加listener,移除listener的操作,这里可以可以初步理解为这里扩展成了一个listener的容器。。


另外LifecycleBase的定义中,还扩展了基本的启动,停止操作什么的。。。

例如当组件启动的时候,就需要更改当前组件的状态,并调用相应的listener。。。这里就拿初始化的方法来举例子吧:

    //这里扩展了init方法,这里首先设置当前组件的状态,
    @Override
    public final synchronized void init() throws LifecycleException {
        if (!state.equals(LifecycleState.NEW)) {
            invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }
        setStateInternal(LifecycleState.INITIALIZING, null, false);  //设置当前的状态为INITIALIZING

        try {
            initInternal();  //调用该方法用于初始化,具体的实现在子类中
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            setStateInternal(LifecycleState.FAILED, null, false);
            throw new LifecycleException(
                    sm.getString("lifecycleBase.initFail",toString()), t);
        }

        setStateInternal(LifecycleState.INITIALIZED, null, false);  //将对象设置为INITIALIZED状态
    }

 //具体初始化的方法啊,在子类中实现
    protected abstract void initInternal() throws LifecycleException;

这里应该代码很容易能理解吧,无非就是对当前组件的装填进行验证,并修改组件的状态,当然在设置组件的状态的时候还伴随着对listener的调用。。。

最后再调用initInternal方法进行初始化,当然这个方法需要在具体的子类中进行实现。。。。


另外这里还要介绍一个比较特殊的LifeCycle的抽象层,LifecycleMBeanBase,它继承了抽象类LifecycleBase类型,其实这里看名字就能够知道这个抽象层要干些啥事情了吧。。。。来看一段代码:

    protected void initInternal() throws LifecycleException {

        // If oname is not null then registration has already happened via
        // preRegister().
        if (oname == null) {
            mserver = Registry.getRegistry(null, null).getMBeanServer();  //获取用到的mbserver

            oname = register(this, getObjectNameKeyProperties());  //注册当前组件到mbserver
        }
    }

嗯,其实就是在组件的初始化的时候对当前组件在JMX上进行注册,具体Tomcat的JMX部分内容,在前面的文章中就已经说过了,这里就不详细说了。。。

也就是说,如果一个类型需要在JMX上进行注册,那么它需要继承LifeCycleMBeanBase抽象类,然后实现其中的几个抽象方法。。。


好啦,到这里位置,LifeCycle部分的内容就算差不多了。。

总的感觉,Tomcat在LifeCycle部分的设计还算是比较简单的。。。。


好啦,接下来来看看Server部分的内容吧。。。首先来看看最顶层的接口的定义:



package org.apache.catalina;

import java.io.File;

import org.apache.catalina.deploy.NamingResourcesImpl;
import org.apache.catalina.startup.Catalina;


//顶层的server接口的定义,继承了生命周期接口
public interface Server extends Lifecycle {

    // ------------------------------------------------------------- Properties

    /**
     * Return the global naming resources.
     */
    public NamingResourcesImpl getGlobalNamingResources();


    /**
     * Set the global naming resources.
     *
     * @param globalNamingResources The new global naming resources
     */
    public void setGlobalNamingResources
        (NamingResourcesImpl globalNamingResources);


    /**
     * Return the global naming resources context.
     */
    public javax.naming.Context getGlobalNamingContext();


    /**
     * Return the port number we listen to for shutdown commands.
     */
    public int getPort();  //用于监听shutdown命令的端口


    /**
     * Set the port number we listen to for shutdown commands.
     *
     * @param port The new port number
     */
    public void setPort(int port);  用于监听shutdown命令的端口


    /**
     * Return the address on which we listen to for shutdown commands.
     */
    public String getAddress();  //用于监听shutdown命令的地址


    /**
     * Set the address on which we listen to for shutdown commands.
     *
     * @param address The new address
     */
    public void setAddress(String address);  //用于监听shutdown命令的地址


    /**
     * Return the shutdown command string we are waiting for.
     */
    public String getShutdown();


    /**
     * Set the shutdown command we are waiting for.
     *
     * @param shutdown The new shutdown command
     */
    public void setShutdown(String shutdown);


    public ClassLoader getParentClassLoader();   //这个server对象用的classLoader,一般是catalina  loader


    public void setParentClassLoader(ClassLoader parent);


 
    public Catalina getCatalina();  //获取catalina对象

 
    public void setCatalina(Catalina catalina);  //设置用的catalina对象

    public File getCatalinaBase();    //一般情况下都是tomcat的根路径

    public void setCatalinaBase(File catalinaBase);  

    public File getCatalinaHome();

    public void setCatalinaHome(File catalinaHome);


    public void addService(Service service);   //添加service对象


    public void await();


    public Service findService(String name);    //根据名字获取某个service

    public Service[] findServices();  //获取所有的service

    public void removeService(Service service);  //删除一个service
}

嗯,其实最顶层的Server接口的定义也很简单,扩展了lifeCycle接口其中最重要的部分无非是对service的添加以及移除。。。

给人最大的干吼就是它是一个service的容器


好啦,接下来来看看最常用的类型StandardServer吧,这里它不光实现了Server接口,还继承了LifecycleMBeanBase类型,这里也就表示StandardServer将会被注册到JMX上面去的。。。

由于它的代码比较长,这里就不直接贴出来了。。来比较重要的属性定义吧:

    private Service services[] = new Service[0];   //用于保存所有的service,是一个数组啊
    private final Object servicesLock = new Object();

嗯,一个service的数组。。。。嗯,容器嘛。。。


好了,这里也就稍微的来看看初始话和启动两个方法的实现吧:

    protected void initInternal() throws LifecycleException {

        super.initInternal();   //父类的init,它里面主要是进行对象在mbserver上面注册当前对象

        // Register global String cache
        // Note although the cache is global, if there are multiple Servers
        // present in the JVM (may happen when embedding) then the same cache
        // will be registered under multiple names
        onameStringCache = register(new StringCache(), "type=StringCache");

        // Register the MBeanFactory
        MBeanFactory factory = new MBeanFactory();  //创建MBeanFactory
        factory.setContainer(this);   //设置当前mbeanfactory的container
        onameMBeanFactory = register(factory, "type=MBeanFactory");  //注册mbeanfactory

        // Register the naming resources
        globalNamingResources.init(); //初始计划名字资源

        // Populate the extension validator with JARs from common and shared
        // class loaders
        if (getCatalina() != null) {   //获取catalina对象
            ClassLoader cl = getCatalina().getParentClassLoader();  //在bootstrap里面设置成了shareloader
            // Walk the class loader hierarchy. Stop at the system class loader.
            // This will add the shared (if present) and common class loaders
            //加载classLoader里面的路径的资源,这里会向上遍历classLoader
            while (cl != null && cl != ClassLoader.getSystemClassLoader()) {
                if (cl instanceof URLClassLoader) {
                    URL[] urls = ((URLClassLoader) cl).getURLs();
                    for (URL url : urls) {
                        if (url.getProtocol().equals("file")) {
                            try {
                                File f = new File (url.toURI());
                                if (f.isFile() &&
                                        f.getName().endsWith(".jar")) {
                                    ExtensionValidator.addSystemResource(f);
                                }
                            } catch (URISyntaxException e) {
                                // Ignore
                            } catch (IOException e) {
                                // Ignore
                            }
                        }
                    }
                }
                cl = cl.getParent();
            }
        }
        // Initialize our defined Services
        for (int i = 0; i < services.length; i++) {  //初始化service
            services[i].init();
        }
    }

首先是初始化,这里最重要的事情其实是对当前包含的所有的service的初始化,另外还有一些其他的操作,注释应该也算是交代的比较清楚吧。。。


    //父类中定义的抽象方法扩展了lifecycle的start方法,用于启动当前的对象,这里月就是启动tomcat,其实是启动server的service
    @Override
    protected void startInternal() throws LifecycleException {

        fireLifecycleEvent(CONFIGURE_START_EVENT, null);
        setState(LifecycleState.STARTING);

        globalNamingResources.start();

        // Start our defined Services
        synchronized (servicesLock) {
            for (int i = 0; i < services.length; i++) {   //遍历当前的service,然后启动他们
                services[i].start();
            }
        }
    }

启动方法,这里其实最主要的也还是对Service的启动。。。


好了,到这里,Server大体的东西就这些吧,其实干货不多。。。

干活最多的地方应该在Connector部分,不过这个以后再写吧。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Tomcat源码解析是对Tomcat服务器的源代码进行分析和解读的过程。通过对Tomcat源码的研究,可以深入了解Tomcat的整体架构、连接器的内部结构、容器分析以及Tomcat的启动流程等方面的内容。 Tomcat的整体架构包括配置文件server.xml的分析和连接器的内部结构。配置文件server.xml是Tomcat的主要配置文件,通过对其进行分析可以了解Tomcat的各个组件和配置项的作用。连接器是Tomcat的核心组件之一,负责处理客户端请求并将其转发给相应的容器进行处理。 Tomcat的启动流程是通过实现Lifecycle接口的各个组件来完成的。在启动过程中,Tomcat会按照一定的顺序初始化和启动各个组件,确保它们能够正常工作。具体的启动流程可以通过阅读源码中的相关方法和注释来了解。 Tomcat底层使用了Netty来实现IO相关的操作,但与Netty有所区别,因为Tomcat对部分处理进行了封装。通过对Tomcat源码的学习,可以了解Tomcat底层的实现逻辑、各个组件的配合方式以及各种设计模式的交互。 如果你对Tomcat源码解析感兴趣,可以参考提供的源码和相关文章进行深入研究。通过深入研究Tomcat源码,你可以更好地理解Tomcat的工作原理和内部机制。 #### 引用[.reference_title] - *1* [Tomcat源码分析](https://blog.csdn.net/sun_code/article/details/123554480)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [tomcat线程模型-源码解析](https://blog.csdn.net/qq_16498553/article/details/126080174)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值