Tomcat 9 源码解析 -- tomcat框架设计(源码层次解析)

Tomcat 9 源码解析 -- tomcat框架设计

前文已经从架构层次讲解了tomcat框架设计,以及tomcat使用,以及每个模块的作用,以及各功能模块之间的关系。

下面是Tomcat 9 架构的一个启用的架构流程图:

1、Bootstrap类

主要是其中的 main 启动方法:

public static void main(String args[]) {
    	
    	LogPropertiesTest.debug("1、BootStrap 启动开始  ");
    	
        synchronized (daemonLock) {
            if (daemon == null) {
                // Don't set daemon until init() has completed
                Bootstrap bootstrap = new Bootstrap();
                try {
                	// 此处重点
                    bootstrap.init();
                } catch (Throwable t) {
                    handleThrowable(t);
                    t.printStackTrace();
                    return;
                }
                daemon = bootstrap;
            } else {
                // When running as a service the call to stop will be on a new
                // thread so make sure the correct class loader is used to
                // prevent a range of class not found exceptions.
                Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
            }
        }

        
        try {
            String command = "start";
            if (args.length > 0) {
                command = args[args.length - 1];
            }

            if (command.equals("startd")) {
                args[args.length - 1] = "start";
                daemon.load(args);
                daemon.start();
            } else if (command.equals("stopd")) {
                args[args.length - 1] = "stop";
                daemon.stop();
                
                
                
            //  Bootstrap类首先会创建一个本类对象, 然后调用init()方法进行初始化. 执行完init()            方法后会判断启动参数的值, 
            //  由于我们采取默认的启动方式, 所以main方法的参数是start, 会进入下面的判断代码块    
                
            //  此处是重要入口。
                
            } else if (command.equals("start")) {
                daemon.setAwait(true);
                
                // 可以看到在设置等待后, 调用了本类对象的load()方法. 我们跟进查看load()方法的源码.
                daemon.load(args);
                
                LogPropertiesTest.debug("BootStrap : 调用 Bootstrap 的方法 start() ");
                daemon.start();
            } else if (command.equals("stop")) {
                daemon.stopServer(args);
            } else if (command.equals("configtest")) {
                daemon.load(args);
                if (null==daemon.getServer()) {
                    System.exit(1);
                }
                System.exit(0);
            } else {
                log.warn("Bootstrap: command \"" + command + "\" does not exist.");
            }
        } catch (Throwable t) {
            // Unwrap the Exception for clearer error reporting
            if (t instanceof InvocationTargetException &&
                    t.getCause() != null) {
                t = t.getCause();
            }
            handleThrowable(t);
            t.printStackTrace();
            System.exit(1);
        }

    }

其中比较重要的地方 

bootstrap.init();        调用初始化

daemon.load(args); 调用load加载信息    --- 》  此处会调用Catalina的load方法。

daemon.start();         调用开始方法         ----》  此处会调用Catalina的start方法。

 

2、Catalina类 的调用

 Catalina类的load()方法:

/**
     *	开启一个新的 server 。  Start a new server instance.
     * 	关键的有2部分,     111111. 就是 第一步创建Digester . 222222.第二步 在2处进行了解析
     */
    public void load() {
    	
    	LogPropertiesTest.debug("7、Catalina : 调用 Catalina 的方法 load() ");
    	
    	// 判断是否第一场加载
        if (loaded) {
            return;
        }
        loaded = true;

        long t1 = System.nanoTime();

        // Java输入输出临时路径
        initDirs();

        // Before digester - it may be needed
        initNaming();

        // Create and execute our Digester   类似 一个解析 server.xml 的解析器。
        //  tomcat使用Digester类来解析相关的xml文件,包括web.xml和server.xml,我们先讨论下server.xml .
        // 1111111111111111.
        Digester digester = createStartDigester();

        
        ..........
        
            
        /// 2222222222.
        inputSource.setByteStream(inputStream);
        digester.push(this);

        ...........

        // 解析 server.xml     解析 rules,通过rules创建对象执行对象。此处内部调用Server的set    方法,以及其它规则。
        digester.parse(inputSource);


        ...........
        
        // Start the new server
        //一系列的初始化,  首先是Server的初始化 org.apache.catalina.core.StandardServer
        //第二是Service的初始化 org.apache.catalina.core.StandardService
        // StandardServer 继承自 LifecycleBase ,调用 LifecycleBase init方法。
        	
        getServer().init();


        ..........



}

源码中比较重要的几个步骤:

  •  

// Create and execute our Digester   类似 一个解析 server.xml 的解析器。
//  tomcat使用Digester类来解析相关的xml文件,包括web.xml和server.xml,我们先讨论下server.xml .
Digester digester = createStartDigester();

  •  

 // 解析 server.xml     解析 rules,通过rules创建对象执行对象。此处内部调用Server的set方法,以及其它规则。
 digester.parse(inputSource);            ----------》 此处会通过Digester的parse机制将StandardServer对象设置到Catalina对象中。

  •  

//一系列的初始化,首先是Server的初始化 org.apache.catalina.core.StandardServer
//第二是Service的初始化 org.apache.catalina.core.StandardService
// StandardServer 继承自 LifecycleBase ,调用 LifecycleBase init方法。
getServer().init();

Catalina类的start()方法:

public void start() {

        if (getServer() == null) {
            load();
        }

        if (getServer() == null) {
            log.fatal("Cannot start server. Server instance is not configured.");
            return;
        }

        long t1 = System.nanoTime();

        // Start the new server
        try {
        	// 首先是Server的 start 方法 org.apache.catalina.core.StandardServer
            getServer().start();
        } catch (LifecycleException e) {
            log.fatal(sm.getString("catalina.serverStartFail"), e);
            try {
                getServer().destroy();
            } catch (LifecycleException e1) {
                log.debug("destroy() failed for failed Server ", e1);
            }
            return;
        }
        
        ......



}

最重要的调用部分就是

// 首先是Server的 start 方法 org.apache.catalina.core.StandardServer
 getServer().start();    调用  StandardServer的start()方法。

 

3、Server类的调用

首先看一下Server的init方法。

server的类继承关系如下图所示:

其中类中的方法如下,你可以看到  调用StandardServer中的 init()或者start()方法其实都是在调用LifecycleBase类中的方法,然后LifecycleBase中的init()或者start()方法 调用类具体实现子类的

initInternal();

startInternal();方法,此处应该使用了 java的模板模式

 

StandardServer类的initInternal()方法

@Override
    protected void initInternal() throws LifecycleException {

        // 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();
        factory.setContainer(this);
        onameMBeanFactory = register(factory, "type=MBeanFactory");

        // Register the naming resources
        globalNamingResources.init();

        .......

        // Initialize our defined Services
        // 初始化  services    org.apache.catalina.core.StandardService
        for (int i = 0; i < services.length; i++) {
            services[i].init();
        }
    }

最重要的还是最后哪一行

services[i].init(); 直接变成调用 Service的init()方法了。

 

StandardServer类的startInternal()方法

@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++) {
            	 // 初始化  services    org.apache.catalina.core.StandardService
                services[i].start();
            }
        }
    }

 向下一个流程进行,则继续调用service的方法。

services[i].start();

 

4、Service类 的调用

首先还是看一下service类的一个继承关系:其实跟上面 Server类 的实现类似。

 

StandardService类的startInternal()方法

@Override
    protected void initInternal() throws LifecycleException {
        super.initInternal();

        if (engine != null) {
        	// 初始化
            engine.init();
        }

        // Initialize any Executors
        for (Executor executor : findExecutors()) {
            if (executor instanceof JmxEnabled) {
                ((JmxEnabled) executor).setDomain(getDomain());
            }
            // Executor 初始化
            executor.init();
        }

        // Initialize mapper listener
        mapperListener.init();

        // Initialize our defined Connectors
        synchronized (connectorsLock) {
            for (Connector connector : connectors) {
            	// 初始化  Connectors      Connector   org.apache.catalina.connector
                connector.init();
            }
        }
    }

看方法最重要的地方:

  1. // 初始化
    engine.init();                对应的是  StandardEngin
  2. // Executor 初始化       对应的是  StandardThreadExecutor
    executor.init();
  3. connector.init();

StandardService类的startInternal()方法

@Override
    protected void startInternal() throws LifecycleException {

    	LogPropertiesTest.debug("10、StandardService :  执行  startInternal() 方法; 执行类 :"+this.getClass());
    	
        if(log.isInfoEnabled())
            log.info(sm.getString("standardService.start.name", this.name));
        setState(LifecycleState.STARTING);

        // Start our defined Container first
        if (engine != null) {
            synchronized (engine) {
            	LogPropertiesTest.debug("10、StandardService :  执行 Engine 的  engine.start(); 方法; 执行类 :"+this.getClass());
                engine.start();
            }
        }

        synchronized (executors) {
            for (Executor executor: executors) {
            	LogPropertiesTest.debug("10、StandardService :  执行 Executor的 executor.start();; 方法; 执行类 :"+this.getClass());
                executor.start();
            }
        }

        mapperListener.start();

        // Start our defined Connectors second
        synchronized (connectorsLock) {
            for (Connector connector: connectors) {
                // If it has already failed, don't try and start it
                if (connector.getState() != LifecycleState.FAILED) {
                	LogPropertiesTest.debug("10、StandardService :  执行 Connector的  connector.start(); 方法; 执行类 :"+this.getClass());
                	// 初始化  Connectors      Connector   org.apache.catalina.connector
                    connector.start();
                }
            }
        }
    }
  1. // 初始化
    engine.start();                对应的是  StandardEngin
  2. // Executor 初始化       对应的是  StandardThreadExecutor
    executor.start();
  3. connector.start();

 

 

后面的几个类

StandardEngin

StandardHost

StandardContext

的初始化和开始方法和上面的机制都是类似此处就不再贴出源码了。

 

关于Connector类 与 ProtocolHandler类如何进行初始化,以及开启服务的可以看我之前写过的两篇文章

Tomcat 9 源码解析 -- Connector组件

Tomcat 9 源码解析 -- Connector组件(2)

这两篇文章讲解了  Connector组件  如何作为   Service服务  与  Socket套接字   之间的桥梁。

 

 

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值