Proceso central de inicio de Tomcat-Tomcat

Primero, el proceso central del inicio de Tomcat

  Les presenté el diseño del ciclo de vida en Tomcat. Dominar esto es muy útil para que analicemos el proceso central de Tomcat, es decir, necesitamos crear componentes centrales relacionados, como Servidor y Servicio. método de ciclo.

imagen.png

1. Iniciar la entrada

  Puede iniciar el servicio Tomcat a través de una secuencia de comandos (startup.bat), pero si observa los comandos de la secuencia de comandos, encontrará que finalmente se llama al método principal en Bootstrap, por lo que debemos comenzar desde el método principal.

imagen.png

  Luego miramos el código en el método principal, hay tres métodos en los que debemos centrarnos

  1. método bootstrap.init()
  2. método de carga ()
  3. método de inicio ()

  Es decir, las operaciones principales de Tomcat se completarán con estos tres métodos.

2. método de inicio

  Echemos un vistazo al código en el método init, solo eliminamos los que no son centrales

    public void init() throws Exception {
        // 创建相关的类加载器
        initClassLoaders();
        // 省略部分代码...
        // 通过反射创建了 Catalina 类对象
        Class<?> startupClass = catalinaLoader
            .loadClass("org.apache.catalina.startup.Catalina");
        // 创建了 Catalina 实例
        Object startupInstance = startupClass.getConstructor().newInstance();

        // 省略部分代码...
        String methodName = "setParentClassLoader";
        Class<?> paramTypes[] = new Class[1];
        paramTypes[0] = Class.forName("java.lang.ClassLoader");
        Object paramValues[] = new Object[1];
        paramValues[0] = sharedLoader;
        // 把 sharedLoader 设置为了 commonLoader的父加载器
        Method method =
            startupInstance.getClass().getMethod(methodName, paramTypes);
        method.invoke(startupInstance, paramValues);

        // Catalina 实例 赋值给了 catalinaDaemon
        catalinaDaemon = startupInstance;
    }
复制代码
  1. El primero es llamar al método initClassLoaders(). Este método completará la creación del ClassLoader correspondiente. Esto es más importante. Escribiré un artículo para presentarlo más adelante.
  2. Cree un objeto de clase Catalina a través de la reflexión y cree una instancia de Catalina a través de la reflexión
  3. Se establece la relación padre-hijo del cargador de clases
  4. Usamos la variable miembro catalinaDaemon para registrar la instancia de Catalina que creamos

  Esta es información útil que podemos obtener a través del método bootstrap.init(). Luego continuamos mirando hacia abajo.

3. método de carga

  Entonces veamos que hace el método load, el código es el siguiente:

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

        // Call the load() method
        String methodName = "load"; // 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;
        }
        // catalinaDaemon 就是在 init中创建的 Catalina 对象
        Method method =
            catalinaDaemon.getClass().getMethod(methodName, paramTypes);
        if (log.isDebugEnabled()) {
            log.debug("Calling startup class " + method);
        }
        // 会执行 Catalina的load方法
        method.invoke(catalinaDaemon, param);
    }

复制代码

  El código anterior es muy simple, y también podemos ver que la función de este método es llamar al método de carga de Catalina comentando. Entonces, también debemos agregarlo al método de carga de Catalina para verlo, el código también es relativamente largo, dejando solo el código clave

    public void load() {

        if (loaded) {
            return; // 只能被加载一次
        }
        loaded = true;

        initDirs(); // 废弃的方法

        // Before digester - it may be needed
        initNaming(); // 和JNDI 相关的内容 忽略

        // Create and execute our Digester
        // 创建并且执行我们的 Digester 对象  Server.xml
        Digester digester = createStartDigester();

        // 省略掉了 Digester文件处理的代码

        getServer().setCatalina(this); // Server对象绑定 Catalina对象
        getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
        getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());

        // Stream redirection
        initStreams();
        // 省略掉了部分代码...
         getServer().init(); // 完成 Server  Service Engine Connector等组件的init操作

    }
复制代码

Después de simplificar el código anterior, encontramos que el método Load es bastante simple y hace dos cosas.

  1. El análisis del archivo Server.xml se completa a través del componente Digester bajo Apache
  2. La inicialización de los componentes principales, como el servidor, el servicio, el motor y el conector, se completa mediante el método getServer().init(), que repite el LifecycleBase anterior.

imagen.png

  Si el contenido del ciclo de vida no está claro, consulte la introducción de contenido anterior

4.método de inicio

  Finalmente, veamos el código del método de inicio.

    public void start() throws Exception {
        if (catalinaDaemon == null) {
            init(); // 如果 catalinaDaemon 为空 初始化操作
        }
        // 获取的是 Catalina 中的 start方法
        Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);
        // 执行 Catalina 的start方法
        method.invoke(catalinaDaemon, (Object [])null);
    }
复制代码

  La lógica del código anterior también es muy clara, es decir, el método de inicio del objeto Catalina se llama por reflexión. Así que ve al método de inicio de Catalina para verificar.

    public void start() {

        if (getServer() == null) {
            load(); // 如果Server 为空 重新 init 相关的组件
        }

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

        // Start the new server  关键方法--->启动Server
        try {
            getServer().start();
        } catch (LifecycleException e) {
            // 省略...
        }

        // 省略...

        // Register shutdown hook  注册关闭的钩子
        if (useShutdownHook) {
            // 省略...
        }

        if (await) {
            await();
            stop();
        }
    }
复制代码

  A través del código anterior, podemos encontrar que el código principal sigue siendo el método getServer.start(), es decir, el método de inicio de la anotación relacionada se llama anidado a través del objeto Servidor.

imagen.png

5. Resumen del proceso central

Podemos resumir el proceso central del inicio de Tomcat a través de la siguiente figura

imagen.png

  A partir de la figura, podemos ver que Bootstrap en realidad no hace las cosas principales, y lo hace principalmente Catalina.

¡Trabajar juntos para crear y crecer juntos! Este es el día 20 de mi participación en el "Nuevo plan diario de Nuggets · Desafío de actualización de agosto", haga clic para ver los detalles del evento .

Supongo que te gusta

Origin juejin.im/post/7132710433475002405
Recomendado
Clasificación