专注Java教育14年 全国咨询/投诉热线:400-8080-105
动力节点LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 从源码解析Tomcat初始化

从源码解析Tomcat初始化

更新时间:2020-12-08 17:34:11 来源:动力节点 浏览948次

Tomcat服务器的启动流程很标准化,入口是 BootStrap,统一按照生命周期管理接口 Lifecycle的定义进行启动。首先,调用 init()方法逐级初始化,接着调用 start()方法进行启动,同时,每次调用伴随着生命周期状态变更事件的触发。本文我们来介绍Tomcat启动前的准备工作——Tomcat初始化

 

当Tomcat启动的时候 首先会加载 org.apache.ctalina.startup.BootStrap类。使用eclipse或idea启动tomcat其实就是在启动这个类的main方法,根据类的初始化首先会加载static静态块,然后进入main方法。

 

启动的主要步骤可以围绕BootStrap划分为 static中的准备和main中的初始化(init)、加载 (load)、启动(statrt)。下面我们来看看各个步骤的源码:

 

1、 static

//静态代码块的主要功能是设置工作目录catalinaBaseFile和安装目录catalinaHomeFile

static {

    // Will always be non-null

    String userDir = System.getProperty("user.dir");

 

    // Home first

    String home = System.getProperty(Globals.CATALINA_HOME_PROP);

    File homeFile = null;

 

    if (home != null) {

        File f = new File(home);

        try {

            homeFile = f.getCanonicalFile();

        } catch (IOException ioe) {

            homeFile = f.getAbsoluteFile();

        }

    }

 

    if (homeFile == null) {

        // First fall-back. See if current directory is a bin directory

        // in a normal Tomcat install

        File bootstrapJar = new File(userDir, "bootstrap.jar");

 

        if (bootstrapJar.exists()) {

            File f = new File(userDir, "..");

            try {

                homeFile = f.getCanonicalFile();

            } catch (IOException ioe) {

                homeFile = f.getAbsoluteFile();

            }

        }

    }

 

    if (homeFile == null) {

        // Second fall-back. Use current directory

        File f = new File(userDir);

        try {

            homeFile = f.getCanonicalFile();

        } catch (IOException ioe) {

            homeFile = f.getAbsoluteFile();

        }

    }

 

    catalinaHomeFile = homeFile;

    System.setProperty(

        Globals.CATALINA_HOME_PROP, catalinaHomeFile.getPath());

 

    // Then base

    String base = System.getProperty(Globals.CATALINA_BASE_PROP);

    if (base == null) {

        catalinaBaseFile = catalinaHomeFile;

    } else {

        File baseFile = new File(base);

        try {

            baseFile = baseFile.getCanonicalFile();

        } catch (IOException ioe) {

            baseFile = baseFile.getAbsoluteFile();

        }

        catalinaBaseFile = baseFile;

    }

    System.setProperty(

        Globals.CATALINA_BASE_PROP, catalinaBaseFile.getPath());

}


 2、main

 main方法主要是 init、laod、start  (daemon = bootStrap),当start 方法加载完毕,就标志着tomcat启动完成 。


(1)Init

//这里的主要功能是初始化了三个类加载器和创建了Catalina对象

    //ClassLoader commonLoader = null;

    //ClassLoader catalinaLoader = null;

    //ClassLoader sharedLoader = null;

public void init() throws Exception {

    //初始化三个类加载器

    initClassLoaders();

 

    Thread.currentThread().setContextClassLoader(catalinaLoader);

 

    SecurityClassLoad.securityClassLoad(catalinaLoader);

 

    // Load our startup class and call its process() method

    if (log.isDebugEnabled())

        log.debug("Loading startup class");

    //通过反射创建Catalina对象

    Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");

    Object startupInstance = startupClass.getConstructor().newInstance();

 

    // Set the shared extensions class loader

    if (log.isDebugEnabled())

        log.debug("Setting startup class properties");

    //为Catalina对象设置类加载器sharedLoader

    String methodName = "setParentClassLoader";

    Class<?> paramTypes[] = new Class[1];

    paramTypes[0] = Class.forName("java.lang.ClassLoader");

    Object paramValues[] = new Object[1];

    paramValues[0] = sharedLoader;

    Method method =

        startupInstance.getClass().getMethod(methodName, paramTypes);

    method.invoke(startupInstance, paramValues);

 

    catalinaDaemon = startupInstance;

}


(2)laod :比较复杂 ,涉及server、service、connector、engin、可分为如下几步  注意:load过程中并且有对 host、wapper 进行初始化 

   //这里是通过反射转调Catalina对象的load方法

private void load(String[] arguments) throws Exception {

    // Call the load() method

    String methodName = "load";

    Object param[];

    Class<?> paramTypes[];

    if (arguments==null || arguments.length==0) {

        paramTypes = null;

        param = null;

    } else {

        paramTypes = new Class[1];

        paramTypes[0] = arguments.getClass();

        param = new Object[1];

        param[0] = arguments;

    }

    Method method =

        catalinaDaemon.getClass().getMethod(methodName, paramTypes);

    if (log.isDebugEnabled()) {

        log.debug("Calling startup class " + method);

    }

    method.invoke(catalinaDaemon, param);

}  


然后又重新定义了initInternal()抽象方法,server、service、engine、connector等各自间接或直接的实现了 LifeCycleBase类并实现了initlnernal()的方法,因此在他们进行初始化的时候会调用自己的initlnternal()实现。


以上就是通过源码来对Tomcat初始化的分析,通过源码我们能够直截了当的看出Tomcat服务器初始化过程中调用的方法以及各种内部变化。Tomcat初始化也只是Tomcat服务器整体工作流程中的第一步,想要学习和了解整个过程的小伙伴请到本站的Tomcat服务器教程中一边学习一边思考。


提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>