Tomcat启动流程分析

来源

本文整理自 <Tomcat内核设计剖析>、<Tomcat结构解析> 加上自己的理解、源码来自 Tomcat8.5 版本

Tomcat启动流程分析

Init流程时序图

Start流程时序图

Bootstrap

// org.apache.catalina.startup.Bootstrap
public static void main(String args[]) {
    if (daemon == null) {
        // 先创建一个  bootstrap 实例
        Bootstrap bootstrap = new Bootstrap();
        try {
            bootstrap.init();
        } catch (Throwable t) {
            return;
        }
        daemon = bootstrap;
    } else {
        Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
    }

    try {
        // 默认执行 start 方法
        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();
        } else if (command.equals("start")) {
            // 是否让主线程不退出
            daemon.setAwait(true);
            // 反射调用 catalinaDaemon#load 方法,根据server.xml 创建服务
            daemon.load(args);
            // 反射调用 catalinaDaemon#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);
        }
    }
}

/**
     * Initialize daemon.
     * @throws Exception Fatal initialization error
     */
public void init() throws Exception {
    // 初始化类加载器
    initClassLoaders();
    Thread.currentThread().setContextClassLoader(catalinaLoader);
    SecurityClassLoad.securityClassLoad(catalinaLoader);
    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;
    // 反射调用 Catalina 类的 setParentClassLoader 方法。
    Method method =
        startupInstance.getClass().getMethod(methodName, paramTypes);
    method.invoke(startupInstance, paramValues);
    catalinaDaemon = startupInstance;
}

private void initClassLoaders() {
    try {
        commonLoader = createClassLoader("common", null);
        if( commonLoader == null ) {
            commonLoader=this.getClass().getClassLoader();
        }
        catalinaLoader = createClassLoader("server", commonLoader);
        sharedLoader = createClassLoader("shared", commonLoader);
    } catch (Throwable t) {
        System.exit(1);
    }
}

流程图

Catalina

// org.apache.catalina.startup.Catalina

// 设置 await值,会在start方法中服务器启动完成后来判断是否进入等待状态
// true :后续会去监听8005端口
// false:运行完成后就退出
public void setAwait(boolean b) {
    await = b;
}

public void load() {
    // 已经加载就返回
    if (loaded) { return; }
    // 设置加载状态
    loaded = true;
    // 在解析之前,设置一些系统属性
    initNaming();
    // 通过 digester 解析 server.xml 配置文件
    Digester digester = createStartDigester();
    InputSource inputSource = null;
    InputStream inputStream = null;
    File file = null;
    try {
        try {
            // 默认指定了 conf/server.xml 
            file = configFile();
            inputStream = new FileInputStream(file);
            inputSource = new InputSource(file.toURI().toURL().toString());
        }
        if (inputStream == null) {
            try {
                inputStream = getClass().getClassLoader()
                    .getResourceAsStream(getConfigFile());
                inputSource = new InputSource
                    (getClass().getClassLoader()
                     .getResource(getConfigFile()).toString());
            }
        }
        if (inputStream == null) {
            // 尝试加载 server-embed.xml 
            try {
                inputStream = getClass().getClassLoader()
                    .getResourceAsStream("server-embed.xml");
                inputSource = new InputSource
                    (getClass().getClassLoader()
                     .getResource("server-embed.xml").toString());
            }
        }
        // 依旧找不到文件,返回
        if (inputStream == null || inputSource == null) {
            return;
        }
        try {
            inputSource.setByteStream(inputStream);
            digester.push(this);
            // 解析 xml
            digester.parse(inputSource);
        }
    }
    getServer().setCatalina(this);
    // 在 static中定义,
    getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
    getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());
    // Replace System.out and System.err with a custom PrintStream
    initStreams();
    // 创建 Server
    getServer().init();
}
/*
Digester 查相关资料:Java解析xml主要由DOM4J(一次读取到内存并解析)、SAX(一次解析一部分),digester本身采用SAX的解析方式,并提供了一层包装,对使用者更加友好,后来独立出来成为apache的Commons下面的[一个单独的子项目](http://commons.apache.org/proper/commons-digester/)。
*/

public void start() {
    if (getServer() == null) {
        load();
    }
    if (getServer() == null) {
        return;
    }
    try {
        // 调用Server的start方法启动服务器
        getServer().start();
    } catch (LifecycleException e) {
        getServer().destroy();
        return;
    }
    // 注册 关闭 钩子方法
    if (useShutdownHook) {
        if (shutdownHook == null) {
            shutdownHook = new CatalinaShutdownHook();
        }
        Runtime.getRuntime().addShutdownHook(shutdownHook);
        LogManager logManager = LogManager.getLogManager();
        if (logManager instanceof ClassLoaderLogManager) {
            ((ClassLoaderLogManager) logManager).setUseShutdownHook(
                false);
        }
    }
    // 此处判断 主线程是否await
    if (await) {
        // 在 StandardServer 中调用,用来监听 8005 端口,
        // 收到 SHUTDOWN 命令关闭 Server
        await();
        stop();
    }
}

Init流程图

Start流程图

StandardServer

@Override
protected void initInternal() throws LifecycleException {
    super.initInternal();
    // 注册全局 String cache
    onameStringCache = register(new StringCache(), "type=StringCache");
    // 注册 MBeanFactory
    MBeanFactory factory = new MBeanFactory();
    factory.setContainer(this);
    onameMBeanFactory = register(factory, "type=MBeanFactory");
    // 注册命名资源
    globalNamingResources.init();

    // Populate the extension validator with JARs from common and shared
    // class loaders
    if (getCatalina() != null) {
        ClassLoader cl = getCatalina().getParentClassLoader();
        while (cl != null && cl != ClassLoader.getSystemClassLoader()) {
            if (cl instanceof URLClassLoader) {
                URL[] urls = ((URLClassLoader) cl).getURLs();
                for (URL url : urls) {
                    if (url.getProtocol().equals("file")) {
                        File f = new File (url.toURI());
                        if (f.isFile() &&
                            f.getName().endsWith(".jar")) {
                            ExtensionValidator.addSystemResource(f);
                        }
                    }
                }
            }
            cl = cl.getParent();
        }
    }
    // 初始化定义的所有 Service
    for (int i = 0; i < services.length; i++) {
        services[i].init();
    }
}

@Override
protected void startInternal() throws LifecycleException {
    // 设置状态
    fireLifecycleEvent(CONFIGURE_START_EVENT, null);
    // 触发事件
    setState(LifecycleState.STARTING);
    globalNamingResources.start();
    synchronized (servicesLock) {
        for (int i = 0; i < services.length; i++) {
            services[i].start();
        }
    }
}

@Override
public void await() {
    try {
        // port 默认 8005
        awaitSocket = new ServerSocket(port, 1,
                     InetAddress.getByName(address));
    } catch (IOException e) {
        return;
    }
    // 匹配 SHUTDOWN 命令,用来关闭服务器
    boolean match = command.toString().equals(shutdown);
    if (match) {
        break;
    }
    
    ServerSocket serverSocket = awaitSocket;
    awaitThread = null;
    awaitSocket = null;

    // 关闭Server socket并返回
    if (serverSocket != null) {
        serverSocket.close();
    }
}

StandardService

@Override
protected void initInternal() throws LifecycleException {
    super.initInternal();
    // Engine初始化,一个Service对应一个Engine
    if (engine != null) {
        engine.init();
    }
    // 初始化Executor,默认 不会执行
    for (Executor executor : findExecutors()) {
        if (executor instanceof JmxEnabled) {
            ((JmxEnabled) executor).setDomain(getDomain());
        }
        executor.init();
    }
    // 初始化 MapperListener , 默认 LifecycleMBeanBase.java 
    mapperListener.init();
    // 初始化 Connector,server.xml 配置的 Connector
    synchronized (connectorsLock) {
        for (Connector connector : connectors) {
            connector.init();
        }
    }
}

@Override
protected void startInternal() throws LifecycleException {
    setState(LifecycleState.STARTING);
    if (engine != null) {
        synchronized (engine) {
            engine.start();
        }
    }
    synchronized (executors) {
        for (Executor executor: executors) {
            executor.start();
        }
    }
    mapperListener.start();
    synchronized (connectorsLock) {
        for (Connector connector: connectors) {
            if (connector.getState() != LifecycleState.FAILED) {
                connector.start();
            }
        }
    }
}

ContainerBase

​ 是容器的抽象父类,定义了容器生命周期中公共方法。Engine、Host、Context、Wrapper继承此父类。

@Override
protected void initInternal() throws LifecycleException {
    // 创建 线程池
    BlockingQueue<Runnable> startStopQueue = new LinkedBlockingQueue<>();
    startStopExecutor = new ThreadPoolExecutor(
        getStartStopThreadsInternal(),
        getStartStopThreadsInternal(), 10, TimeUnit.SECONDS,
        startStopQueue,
        new StartStopThreadFactory(getName() + "-startStop-"));
    startStopExecutor.allowCoreThreadTimeOut(true);
    super.initInternal();
}

@Override
protected synchronized void startInternal() throws LifecycleException {
    // 如果有 Cluster和 Realm则调用其 start 方法
    Cluster cluster = getClusterInternal();
    if (cluster instanceof Lifecycle) {
        ((Lifecycle) cluster).start();
    }
    Realm realm = getRealmInternal();
    if (realm instanceof Lifecycle) {
        ((Lifecycle) realm).start();
    }
    // 通过 Future 调用所有子容器的 start方法
    Container children[] = findChildren();
    List<Future<Void>> results = new ArrayList<>();
    for (int i = 0; i < children.length; i++) {
        results.add(startStopExecutor.submit(new StartChild(children[i])));
    }
    boolean fail = false;
    for (Future<Void> result : results) {
        try {
            // 获取子容器 start 方法结果
            result.get();
        } catch (Exception e) {
            log.error(sm.getString("containerBase.threadedStartFailed"), e);
            fail = true;
        }
    }
    if (fail) {
        throw new LifecycleException(
            sm.getString("containerBase.threadedStartFailed"));
    }
    // 启用管道,后面介绍到
    if (pipeline instanceof Lifecycle)
        ((Lifecycle) pipeline).start();
    // 设置状态值
    setState(LifecycleState.STARTING);
    // 启动后台线程,日志输出等工作,
    threadStart();
}

// 开启后台线程,定时检查 session 超时、
protected void threadStart() {
    if (thread != null)
        return;
    if (backgroundProcessorDelay <= 0)
        return;
    threadDone = false;
    String threadName = "ContainerBackgroundProcessor[" + toString() + "]";
    thread = new Thread(new ContainerBackgroundProcessor(), threadName);
    thread.setDaemon(true);
    thread.start();
}

// 内部类 ContainerBackgroundProcessor, 默认 10s一次
// 在 StandardEngine 构造函数中定义
protected void processChildren(Container ContainerBase.this) {
    container.backgroundProcess();
    Container[] children = container.findChildren();
    for (int i = 0; i < children.length; i++) {
        if (children[i].getBackgroundProcessorDelay() <= 0) {
            processChildren(children[i]);
        }
    }
}

@Override
public void backgroundProcess() {
    if (!getState().isAvailable())
        return;
    Cluster cluster = getClusterInternal();
    if (cluster != null) {
        cluster.backgroundProcess();
    }
    Realm realm = getRealmInternal();
    if (realm != null) {
        realm.backgroundProcess();
    }
    Valve current = pipeline.getFirst();
    while (current != null) {
        current.backgroundProcess();
        current = current.getNext();
    }
    fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);
}

// LifecycleBase
protected void fireLifecycleEvent(String type, Object data) {
    LifecycleEvent event = new LifecycleEvent(this, type, data);
    for (LifecycleListener listener : lifecycleListeners) {
        listener.lifecycleEvent(event);
    }
}

// 看一下 HostConfig 的 lifecycleEvent 方法
@Override
public void lifecycleEvent(LifecycleEvent event) {
    if (event.getType().equals(Lifecycle.PERIODIC_EVENT)) {
        // 是否自动部署
        check();
    } else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
        beforeStart();
    } else if (event.getType().equals(Lifecycle.START_EVENT)) {
        start();
    } else if (event.getType().equals(Lifecycle.STOP_EVENT)) {
        stop();
    }
}

容器的作用

​ Container的4个容器是逐层包含的关系。它们之间的关系如下图:

1、Engine:用来管理多个站点,一个Service最多只能有一个Engine。

2、Host:代表一个站点,通过配置Host可以添加站点。

3、Context:代表一个应用程序,对应一个WEB-INF目录。

4、Wrapper:每个Wrapper封装一个Servlet。

容器的配置

1、

<Server port="8005" shutdown="SHUTDOWN">
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

    <Engine name="Catalina" defaultHost="localhost">
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
      </Host>
    </Engine>
  </Service>
</Server>
  • Server 在 8005端口监听关闭命令“SHUTDOWN”;
  • Server 中定义了一个 Catalina的Service;
  • Service 中定义了两个Connector:
    • 一个是HTTP协议;
    • 一个是AJP协议(用于集成);
  • Service 中还定义了了一个Catalina的Engine;
  • Engine 中定义了 localhost 的 Host;
    • defaultHost:请求的域名如果在所有的Host的name和Alias中都找不到使用的默认值
  • Host:
    • name:表示域名;
    • appBase:站点的位置;
    • unpackWARS:是否自动解压war包;
    • autoDeploy:是否自动部署;
    • 子标签: :给localhost定义别名;

2、Context通过文件配置的方式一共有5个位置可以配置:

  • conf/server.xml中的Context标签;
  • conf/[enginename]/[hostname]/目录下以应用命名的 xml 文件。
  • 应用自己的 /META-INT/context.xml;
  • conf/context.xml 文件
  • conf/[enginename]/[hostname]/context.xml.default文件;

3、前三个用于配置单独的应用,后面2种是Context共享的。第4种是 整个 Tomcat 共享,第5种配置的内容在对应的站点(Host)中共享。第1种方式只有在Tomcat重启才会重新加载,不推荐使用。

<!-- 
    用于全局配置
    The contents of this file will be loaded for each web application 
-->
<Context>

    <!-- Default set of monitored resources. If one of these changes, the    -->
    <!-- web application will be reloaded.                                   -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
</Context>

4、Wrapper的配置,在web.xml中配置的Servlet,一个Servlet对应一个Wrapper、可以在 conf/web.xml 中配置全局的 Wrapper,处理 Jsp的 JspServlet的配置等。

<servlet>
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    <init-param>
        <param-name>fork</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <param-name>xpoweredBy</param-name>
        <param-value>false</param-value>
    </init-param>
    <load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>jsp</servlet-name>
    <url-pattern>*.jsp</url-pattern>
    <url-pattern>*.jspx</url-pattern>
</servlet-mapping>

<!--配置了 session 超时时间-->
<session-config>
    <session-timeout>30</session-timeout>
</session-config>

<!-- 很多 mime 类型 -->
<mime-mapping>
</mime-mapping>

StandardEngine

public StandardEngine() {
    super();
    // pipeline 设置 basicValve
    pipeline.setBasic(new StandardEngineValve());
    setJvmRoute(System.getProperty("jvmRoute"));
    // 设置等待时间 10
    backgroundProcessorDelay = 10;
}

@Override
protected void initInternal() throws LifecycleException {
    // 没有定义 Realm ,设置一个 NullRealm,权限访问。
    getRealm();
    super.initInternal();
}

@Override
protected synchronized void startInternal() throws LifecycleException {
    super.startInternal();
}

StandardHost

public StandardHost() {
    super();
    // 设置 BasicValve
    pipeline.setBasic(new StandardHostValve());
}

@Override
protected synchronized void startInternal() throws LifecycleException {
    // 设置 error Valve
    String errorValve = getErrorReportValveClass();
    if ((errorValve != null) && (!errorValve.equals(""))) {
        try {
            boolean found = false;
            Valve[] valves = getPipeline().getValves();
            for (Valve valve : valves) {
                if (errorValve.equals(valve.getClass().getName())) {
                    found = true;
                    break;
                }
            }
            if(!found) {
                // 绑定 errorValve
                Valve valve =
                    (Valve) Class.forName(errorValve).getConstructor().newInstance();
                getPipeline().addValve(valve);
            }
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
        }
    }
    super.startInternal();
}

StandardContext

public StandardContext() {
    super();
    // 设置 BasicValve
    pipeline.setBasic(new StandardContextValve());
    // 广播通知
    broadcaster = new NotificationBroadcasterSupport();
    if (!Globals.STRICT_SERVLET_COMPLIANCE) {
        resourceOnlyServlets.add("jsp");
    }
}

@Override
protected synchronized void startInternal() throws LifecycleException {
    // Send j2ee.state.starting notification
    if (this.getObjectName() != null) {
        Notification notification = new Notification("j2ee.state.starting",
                                                     this.getObjectName(), sequenceNumber.getAndIncrement());
        broadcaster.sendNotification(notification);
    }

    setConfigured(false);
    boolean ok = true;

    // namingResources 启动
    if (namingResources != null) {
        namingResources.start();
    }

    // Post work directory
    postWorkDirectory();

    // Add missing components as necessary
    if (getResources() == null) {   // (1) Required by Loader
        try {
            setResources(new StandardRoot(this));
        } catch (IllegalArgumentException e) {
            ok = false;
        }
    }
    if (ok) {
        // 加载 /WEB-INF/classes/META-INF/resources 目录下资源
        resourcesStart();
    }
    // 设置加载器
    if (getLoader() == null) {
        WebappLoader webappLoader = new WebappLoader(getParentClassLoader());
        webappLoader.setDelegate(getDelegate());
        setLoader(webappLoader);
    }

    // cookie 处理器
    if (cookieProcessor == null) {
        cookieProcessor = new Rfc6265CookieProcessor();
    }

    // 初始化 CharsetMapper
    getCharsetMapper();

    // 验证 /META-INF/MANIFEST.MF
    boolean dependencyCheck = true;
    try {
        dependencyCheck = ExtensionValidator.validateApplication
            (getResources(), this);
    } catch (IOException ioe) {
        dependencyCheck = false;
    }

    // // 验证失败, application 不可用
    if (!dependencyCheck) {
        ok = false;
    }

    // catalina.useNaming 环境变量
    String useNamingProperty = System.getProperty("catalina.useNaming");
    if ((useNamingProperty != null)
        && (useNamingProperty.equals("false"))) {
        useNaming = false;
    }

    if (ok && isUseNaming()) {
        if (getNamingContextListener() == null) {
            NamingContextListener ncl = new NamingContextListener();
            ncl.setName(getNamingContextName());
            ncl.setExceptionOnFailedWrite(getJndiExceptionOnFailedWrite());
            // 注册 LifecycleListener
            addLifecycleListener(ncl);
            setNamingContextListener(ncl);
        }
    }

    // Binding thread
    ClassLoader oldCCL = bindThread();

    try {
        if (ok) {
            // Start our subordinate components, if any
            Loader loader = getLoader();
            if (loader instanceof Lifecycle) {
                ((Lifecycle) loader).start();
            }

            // since the loader just started, the webapp classloader is now
            // created.
            setClassLoaderProperty("clearReferencesRmiTargets",
                                   getClearReferencesRmiTargets());
            setClassLoaderProperty("clearReferencesStopThreads",
                                   getClearReferencesStopThreads());
            setClassLoaderProperty("clearReferencesStopTimerThreads",
                                   getClearReferencesStopTimerThreads());
            setClassLoaderProperty("clearReferencesHttpClientKeepAliveThread",
                                   getClearReferencesHttpClientKeepAliveThread());
            setClassLoaderProperty("clearReferencesObjectStreamClassCaches",
                                   getClearReferencesObjectStreamClassCaches());

            // By calling unbindThread and bindThread in a row, we setup the
            // current Thread CCL to be the webapp classloader
            unbindThread(oldCCL);
            oldCCL = bindThread();

            // Initialize logger again. Other components might have used it
            // too early, so it should be reset.
            logger = null;
            getLogger();

            Realm realm = getRealmInternal();
            if(null != realm) {
                if (realm instanceof Lifecycle) {
                    ((Lifecycle) realm).start();
                }

                // Place the CredentialHandler into the ServletContext so
                // applications can have access to it. Wrap it in a "safe"
                // handler so application's can't modify it.
                CredentialHandler safeHandler = new CredentialHandler() {
                    @Override
                    public boolean matches(String inputCredentials, String storedCredentials) {
                        return getRealmInternal().getCredentialHandler().matches(inputCredentials, storedCredentials);
                    }

                    @Override
                    public String mutate(String inputCredentials) {
                        return getRealmInternal().getCredentialHandler().mutate(inputCredentials);
                    }
                };
                context.setAttribute(Globals.CREDENTIAL_HANDLER, safeHandler);
            }

            // 调用事件
            fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);

            // 在不可用的时候,启动子容器
            for (Container child : findChildren()) {
                if (!child.getState().isAvailable()) {
                    child.start();
                }
            }

            // pipeline 的启动
            if (pipeline instanceof Lifecycle) {
                ((Lifecycle) pipeline).start();
            }

            // 获取集群管理器
            Manager contextManager = null;
            Manager manager = getManager();
            if (manager == null) {
                if ( (getCluster() != null) && distributable) {
                    try {
                        contextManager = getCluster().createManager(getName());
                    } catch (Exception ex) {
                        ok = false;
                    }
                } else {
                    contextManager = new StandardManager();
                }
            }

            // 配置默认管理器
            if (contextManager != null) {
                setManager(contextManager);
            }
            // 注册管理器
            if (manager!=null && (getCluster() != null) && distributable) {
                getCluster().registerManager(manager);
            }
        }

        if (!getConfigured()) {
            ok = false;
        }

        // 将资源 放到 servlet Context 中
        if (ok)
            getServletContext().setAttribute
            (Globals.RESOURCES_ATTR, getResources());

        if (ok ) {
            if (getInstanceManager() == null) {
                javax.naming.Context context = null;
                if (isUseNaming() && getNamingContextListener() != null) {
                    context = getNamingContextListener().getEnvContext();
                }
                Map<String, Map<String, String>> injectionMap = buildInjectionMap(
                    getIgnoreAnnotations() ? new NamingResourcesImpl(): getNamingResources());
                setInstanceManager(new DefaultInstanceManager(context,
                                                              injectionMap, this, this.getClass().getClassLoader()));
            }
            getServletContext().setAttribute(
                InstanceManager.class.getName(), getInstanceManager());
            InstanceManagerBindings.bind(getLoader().getClassLoader(), getInstanceManager());
        }

        // Create context attributes that will be required
        if (ok) {
            getServletContext().setAttribute(
                JarScanner.class.getName(), getJarScanner());
        }

        // 设置上下文 init 参数
        mergeParameters();

        // Call ServletContainerInitializers
        for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry :
             initializers.entrySet()) {
            try {
                entry.getKey().onStartup(entry.getValue(),
                                         getServletContext());
            } catch (ServletException e) {
                log.error(sm.getString("standardContext.sciFail"), e);
                ok = false;
                break;
            }
        }

        // 调用 listener
        if (ok) {
            if (!listenerStart()) {
                ok = false;
            }
        }
        // Check constraints for uncovered HTTP methods
        // Needs to be after SCIs and listeners as they may programmatically
        // change constraints
        if (ok) {
            checkConstraintsForUncoveredMethods(findConstraints());
        }
        try {
            // Start manager
            Manager manager = getManager();
            if (manager instanceof Lifecycle) {
                ((Lifecycle) manager).start();
            }
        } catch(Exception e) {
            ok = false;
        }
        // filter调用
        if (ok) {
            if (!filterStart()) {
                ok = false;
            }
        }
        // 初始化 Servlet,如果配置了 LoadOnStartUp
        if (ok) {
            if (!loadOnStartup(findChildren())){
                ok = false;
            }
        }
        // 启动后台线程
        super.threadStart();
    } finally {
        unbindThread(oldCCL);
    }
    // 资源回收
    getResources().gc();

    if (!ok) {
        setState(LifecycleState.FAILED);
    } else {
        setState(LifecycleState.STARTING);
    }
}

StandardWrapper

public StandardWrapper() {
    super();
    swValve = new StandardWrapperValve();
    // 设置 BasicValve
    pipeline.setBasic(swValve);
    broadcaster = new NotificationBroadcasterSupport();
}

@Override
protected synchronized void startInternal() throws LifecycleException {

    // Send j2ee.state.starting notification
    if (this.getObjectName() != null) {
        Notification notification = new Notification("j2ee.state.starting",
                                                     this.getObjectName(),
                                                     sequenceNumber++);
        broadcaster.sendNotification(notification);
    }
    super.startInternal();
    setAvailable(0L);
    // Send j2ee.state.running notification
    if (this.getObjectName() != null) {
        Notification notification =
            new Notification("j2ee.state.running", this.getObjectName(),
                             sequenceNumber++);
        broadcaster.sendNotification(notification);
    }
}

StandardPipeline

@Override
protected void initInternal() { }

@Override
protected synchronized void startInternal() throws LifecycleException {
    Valve current = first;
    if (current == null) {
        current = basic;
    }
    while (current != null) {
        if (current instanceof Lifecycle)
            ((Lifecycle) current).start();
        current = current.getNext();
    }
    setState(LifecycleState.STARTING);
}

猜你喜欢

转载自www.cnblogs.com/wansw/p/10232613.html