Processo principal de inicialização do Tomcat-Tomcat

Primeiro, o processo principal de inicialização do Tomcat

  Apresentei a você o design do ciclo de vida no Tomcat. Dominar isso é muito útil para analisarmos o processo central do Tomcat, ou seja, precisamos criar componentes centrais relacionados, como Server e Service. cycle method.

imagem.png

1. Inicie a entrada

  Você pode iniciar o serviço do Tomcat por meio de um script (startup.bat), mas se você observar os comandos do script, verá que o método principal no Bootstrap é finalmente chamado, portanto, precisamos iniciar pelo método principal

imagem.png

  Então nós olhamos para o código no método principal, existem três métodos que precisamos focar

  1. método bootstrap.init()
  2. método load()
  3. método start()

  Ou seja, as operações principais do Tomcat serão concluídas nesses três métodos.

2. método de inicialização

  Vamos dar uma olhada no código no método init, apenas removemos os não essenciais

    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. A primeira é chamar o método initClassLoaders(). Este método irá completar a criação do ClassLoader correspondente. Isso é mais importante. Vou escrever um artigo para apresentá-lo mais tarde.
  2. Crie um objeto de classe Catalina por meio de reflexão e crie uma instância de Catalina por meio de reflexão
  3. O relacionamento pai-filho do carregador de classes está definido
  4. Usamos a variável de membro catalinaDaemon para registrar a instância Catalina que criamos

  Esta é uma informação útil que podemos obter através do método bootstrap.init(). Então continuamos a olhar abaixo.

3. método de carregamento

  Então vamos ver o que o método load faz. O código é o seguinte:

    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);
    }

复制代码

  O código acima é bem simples, e também podemos ver que a função desse método é chamar o método load da Catalina comentando. Então também precisamos adicioná-lo ao método load da Catalina para visualizar, o código também é relativamente longo, deixando apenas o código da chave

    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操作

    }
复制代码

Depois de simplificar o código acima, descobrimos que o método Load é bem simples e faz duas coisas.

  1. A análise do arquivo Server.xml é concluída através do componente Digester no Apache
  2. A inicialização dos componentes principais, como Servidor, Serviço, Engin e Conector, é concluída por meio do método getServer().init(), que ecoa o LifecycleBase anterior.

imagem.png

  Se o conteúdo do ciclo de vida não estiver claro, consulte a introdução do conteúdo anterior

4. método de início

  Finalmente, vamos ver o código do método start.

    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);
    }
复制代码

  A lógica do código acima também é bem clara, ou seja, o método start do objeto Catalina é chamado por reflexão. Então vá para o método start da 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();
        }
    }
复制代码

  Através do código acima, podemos descobrir que o código central ainda é o método getServer.start(), ou seja, o método start da anotação relacionada é chamado aninhado através do objeto Server.

imagem.png

5. Resumo do processo principal

Podemos resumir o processo central de inicialização do Tomcat através da figura a seguir

imagem.png

  A partir da figura, podemos ver que o Bootstrap não faz as coisas principais, e é feito principalmente pela Catalina.

Trabalhem juntos para criar e crescer juntos! Este é o 20º dia da minha participação no "Nuggets Daily New Plan · August Update Challenge", clique para ver os detalhes do evento .

Acho que você gosta

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