(二)Tomcat架构及运行原理之Container源码分析

本文深入剖析了Tomcat服务器的启动流程,从TomcatReactiveWebServerFactory工厂类的初始化开始,逐步介绍了StandardServer、StandardService、StandardEngine、StandardHost、StandardContext和StandardWrapper等核心组件的初始化和启动过程。重点分析了Lifecycle接口及其子类LifecycleBase的源码作用,以及Container组件的初始化流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.Container部分源码流程

1.1 Lifecycle接口及子类LifecycleBase源码作用

1.2 Tomcat基本架构初始化

1.2.1 TomcatReactiveWebServerFactory

1.2.2 Tomcat

1.2.3 StandardServer

1.3 Container组件初始化

1.3.1 Container接口及ContainerBase实现类

1.3.2 StandardEngine

1.3.3 StandardHost

1.3.4 TomcatEmbeddedContext

1.3.5 StandardContext

1.3.6 StandardWrapper

阅读本篇请先看(一)Tomcat架构及运行原理之基本架构文章。

1.Container部分源码流程

1.1 Lifecycle接口及子类LifecycleBase源码作用

分析Container这一部分源码流程前,接口Lifecycle源码需要我们着重看一下,其部分源码如下:

public interface Lifecycle {
    public static final String BEFORE_INIT_EVENT = "before_init";
    public static final String AFTER_INIT_EVENT = "after_init";
    public static final String START_EVENT = "start";
    public static final String BEFORE_START_EVENT = "before_start";
    public static final String AFTER_START_EVENT = "after_start";
    public static final String STOP_EVENT = "stop";
    public static final String BEFORE_STOP_EVENT = "before_stop";
    public static final String AFTER_STOP_EVENT = "after_stop";
    public static final String AFTER_DESTROY_EVENT = "after_destroy";
    public static final String BEFORE_DESTROY_EVENT = "before_destroy";
    public static final String PERIODIC_EVENT = "periodic";
    public static final String CONFIGURE_START_EVENT = "configure_start";
    public static final String CONFIGURE_STOP_EVENT = "configure_stop";
    public void init() throws LifecycleException;
    public void start() throws LifecycleException;
    public void stop() throws LifecycleException;
    public void destroy() throws LifecycleException;
}

只贴了部分源码和成员变量,其中最重要的属于下面四个方法,这四个方法分别对应初始化、Tomcat启动、Tomcat停止及资源销毁这四个动作。而上面的那些变量只是为了说明抛出异常时具体处于哪个阶段而已,看名字也能够知道其变量具体对应的是哪个操作。

Lifecycle接口有个实现子类LifecycleBase,基本上接口的所有实现类都会继承这个子类,同时实现这个子类的抽象方法,其部分关键源码如下:

public abstract class LifecycleBase implements Lifecycle {
    private volatile LifecycleState state = LifecycleState.NEW;
    @Override
    public final synchronized void init() throws LifecycleException {
        if (!state.equals(LifecycleState.NEW)) {
            invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }
        try {
            setStateInternal(LifecycleState.INITIALIZING, null, false);
            initInternal();
            setStateInternal(LifecycleState.INITIALIZED, null, false);
        } catch (Throwable t) {
            handleSubClassException(t, "...", toString());
        }
    }
    protected abstract void initInternal() throws LifecycleException;
    @Override
    public final synchronized void start() throws LifecycleException {
        if (LifecycleState.STARTING_PREP.equals(state) || 
                LifecycleState.STARTING.equals(state) ||
                LifecycleState.STARTED.equals(state)) {
            return;
        }
        if (state.equals(LifecycleState.NEW)) {
            init();
        } else if (state.equals(LifecycleState.FAILED)) {
            stop();
        } else if (!state.equals(LifecycleState.INITIALIZED) &&
                !state.equals(LifecycleState.STOPPED)) {
            invalidTransition(Lifecycle.BEFORE_START_EVENT);
        }
        try {
            setStateInternal(LifecycleState.STARTING_PREP, null, false);
            startInternal();
            if (state.equals(LifecycleState.FAILED)) {
                stop();
            } else if (!state.equals(LifecycleState.STARTING)) {
                invalidTransition(Lifecycle.AFTER_START_EVENT);
            } else {
                setStateInternal(LifecycleState.STARTED, null, false);
            }
        } catch (Throwable t) {
            handleSubClassException(t, "...", toString());
        }
    }
    protected abstract void startInternal() throws LifecycleException;
}

只看init和start及相关的抽象声明方法,这两个方法实现子类都会调用进来,进而调用进对应的initInternal和startInternal,这两个方法都需要实现子类去实现逻辑。因此等下分析源码的时候,如果调用的init和start,则直接看到实现子类的initInternal和startInternal方法即可,因为父类的这两个方法流程逻辑都没有被重写,全是一样的流程。

init()方法流程:

  1. 检测当前对象生命周期是否为NEW,如果不是则进入invalidTransition方法抛出异常,因此进入到init方法时生命周期一定是NEW;
  2. 设置对象生命周期为INITIALIZING,即初始化中;
  3. 调用initInternal()方法进行实现子类的内部初始化;
  4. 成功调用完initInternal()方法后再将对象生命周期设置成INITIALIZED,即初始化完成。

start()方法流程:

  1. 判断当前对象的生命周期,如果是STARTING_PREP、STARTING或者STARTED三者中的任意一种状态,则代表start方法早就执行过,因此会直接退出;
  2. 判断生命周期是否属于NEW或者FAILED,如果是这两种状态,则分别调用init方法和stop方法,因此直接调用Lifecycle接口的start方法而跳过init方法也是可以的。如果前面的条件不成立会判断状态是否是INITIALIZED和STOPPED,如果是则抛出异常;
  3. 设置当前对象的状态为STARTING_PREP;
  4. 调用子类实现方法startInternal();
  5. 判断状态是否是FAILED、STARTING或者其它状态,如果状态对应则分别执行stop方法、抛出异常或者设置状态为STARTED。

1.2 Tomcat基本架构初始化

1.2.1 TomcatReactiveWebServerFactory

这个类便是Springboot初始化获得Tomcat的工厂,在这里面会完成Spring对Tomcat的一些初始化以及其它的操作,当然和本期最相关的便是在启动Tomcat前构建运行对象结构。看下列源码:

public class TomcatServletWebServerFactory 
        extends AbstractServletWebServerFactory
        implements ConfigurableTomcatWebServerFactory, 
                ResourceLoaderAware {
    public static final String DEFAULT_PROTOCOL = 
            "org.apache.coyote.http11.Http11NioProtocol";
    private String protocol = DEFAULT_PROTOCOL;
    @Override
    public WebServer getWebServer(
            ServletContextInitializer... initializers) {
       Tomcat tomcat = new Tomcat();
       File baseDir = (this.baseDirectory != null) ? 
               this.baseDirectory : createTempDir("tomcat");
       tomcat.setBaseDir(baseDir.getAbsolutePath());
       // 一、创建了connector
       Connector connector = new Connector(this.protocol);
       // 二、调用了getService,这个方法中会调用getServer,再调用getService
       // 这一个方法就完成了server和service两层关系的创建
       tomcat.getService().addConnector(connector);
       customizeConnector(connector);
       tomcat.setConnector(connector);
       // 三、调用getHost,这里面会先调用getEngine,然后判断engine中是否有
       // host对象,如果没有则新建一个StandardHost对象,显然最开始是没有的
       // 所以这个方法中创建了host,并将engine和host的层级关系创建了
       tomcat.getHost().setAutoDeploy(false);
       configureEngine(tomcat.getEngine());
       for (Connector additionalConnector : 
               this.additionalTomcatConnectors) {
          tomcat.getService().addConnector(additionalConnector);
       }
       // 接下来是这个设置context的方法
       prepareContext(tomcat.getHost(), initializers);
       return getTomcatWebServer(tomcat);
    }
    protected void prepareContext(Host host, 
            ServletContextInitializer[] initializers) {
       TomcatEmbeddedContext context = new TomcatEmbeddedContext();
       // 一系列设置context属性的方法便不看了,如设置name、path这些
       ...
       WebappLoader loader = 
               new WebappLoader(context.getParentClassLoader());
       loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class
               .getName());
       loader.setDelegate(true);
       context.setLoader(loader);
       // isRegisterDefaultServlet默认是true
       // 因此默认情况下会创建一个defaultServlet
       if (isRegisterDefaultServlet()) {
          // 添加一个defaultServlet,具体细节有兴趣的可以自己去看,很简单
          addDefaultServlet(context);
       }
       ...
       context.addLifecycleListener(new StaticResourceConfigurer(context));
       ServletContextInitializer[] initializersToUse = 
               mergeInitializers(initializers);
       // 四、context类型是TomcatEmbeddedContext,将其添加进了host中
       // 至此,显式的server->service->engine->host->context和connector
       // 集成到service中便完成
       host.addChild(context);
       // 这里面将会把TomcatStarter添加到context中,其实现了
       // ServletContainerInitializer接口,可以在context
       // 调用start方法流程中被调用
       configureContext(context, initializersToUse);
       postProcessContext(context);
    }
}

 其中涉及到的getHost、getServer和getService等方法在后面会贴出来。

1.2.2 Tomcat

首先看入口类Tomcat的部分关键源码:

public class Tomcat {
    protected Server server;
    public void start() throws LifecycleException {
        getServer();
        server.start();
    }
    public Server getServer() {
        if (server != null) {
            return server;
        }
        System.setProperty("catalina.useNaming", "false");
        server = new StandardServer();
        initBaseDir();
        ConfigFileLoader.setSource(
                new CatalinaBaseConfigurationSource(new File(basedir), 
                null));
        server.setPort( -1 );
        Service service = new StandardService();
        service.setName("Tomcat");
        server.addService(service);
        return server;
    }
    public Service getService() {
        return getServer().findServices()[0];
    }
    public Engine getEngine() {
        Service service = getServer().findServices()[0];
        if (service.getContainer() != null) {
            return service.getContainer();
        }
        Engine engine = new StandardEngine();
        engine.setName( "Tomcat" );
        engine.setDefaultHost(hostname);
        engine.setRealm(createDefaultRealm());
        service.setContainer(engine);
        return engine;
    }
    public Host getHost() {
        Engine engine = getEngine();
        if (engine.findChildren().length > 0) {
            return (Host) engine.findChildren()[0];
        }
        Host host = new StandardHost();
        host.setName(hostname);
        getEngine().addChild(host);
        return host;
    }
}

 在Springboot启动时会在TomcatWebServer类的initialize()方法中直接调用Tomcat的start()方法,因此我们分析Tomcat的流程就从start方法开始分析。这个方法只有两个步骤:调用getServer方法,接着调用server对象的start方法。getServer方法中如果server对象不为空直接返回,如果为空则实例化一个StandardServer赋值给server,并为其添加一个默认的StandardService对象。至此,跑到server的start方法中至少能够保证tomcat-server-service这三层已经创建成功。

而下面的getEngine和getHost和上面所说的操作基本一致,无需多言。

上一小节我们已经知道了start方法如果状态是NEW则会先调用init方法,而当前所有对象都是NEW,因为是新创建的,所以下面的对象我们直接看initInternal和startInternal方法的实现源码就好。在看源码时由于里面的方法流程都挺长的,因此把流程说明直接写在代码中。

1.2.3 StandardServer

首先看到StandardServer类中的部分关键源码:

public final class StandardServer extends LifecycleMBeanBase 
        implements Server {
    public StandardServer() {
        super();
        // 这是Tomcat的Naming组件,主要是用来加载绑定Tomcat配置文件配置的属性
        // 及标签名字,并最终放入Context中
        globalNamingResources = new NamingResourcesImpl();
        globalNamingResources.setContainer(this);
        if (isUseNaming()) {
            namingContextListener = new NamingContextListener();
            addLifecycleListener(namingContextListener);
        } else {
            namingContextListener = null;
        }
    }
    // 默认的Server名称
    private String address = "localhost";
    // Server下的多个Service对象
    private Service services[] = new Service[0];
    private final Object servicesLock = new Object();
    // 等下会使用到的核心线程数量
    protected int utilityThreads = 2;
    // Java官方线程池
    private ScheduledThreadPoolExecutor utilityExecutor = null;
    // Tomcat自身封装的线程池
    private ScheduledExecutorService utilityExecutorWrapper = null;
    @Override
    protected void initInternal() throws LifecycleException {
        super.initInternal();
        // 配置线程池
        reconfigureUtilityExecutor(
                getUtilityThreadsInternal(utilityThreads));
        register(utilityExecutor, "type=UtilityExecutor");
        // 寄存器全局字符串缓存
        onameStringCache = register(new StringCache(), "type=StringCache");
        // 注册MBeanFactory
        MBeanFactory factory = new MBeanFactory();
        factory.setContainer(this);
        onameMBeanFactory = register(factory, "type=MBeanFactory");
        // 注册初始化globalNamingResources对象
        globalNamingResources.init();
        ...
        // 依次调用services对象的init方法,初始化Server下的service
        for (int i = 0; i < services.length; i++) {
            services[i].init();
        }
    }
    private synchronized void reconfigureUtilityExecutor(int threads) {
        // initInternal方法将会调用进来
        // ScheduledThreadPoolExecutor线程池看过Java线程池源码的就能知道
        // 使用线程池构只需要指定CorePoolSize参数,不需要配置MaximumPoolSize
        // MaximumPoolSize参数默认是int的最大数量
        if (utilityExecutor != null) {
            utilityExecutor.setCorePoolSize(threads);
        } else {
            // 创建线程池
            ScheduledThreadPoolExecutor scheduledThreadPoolExecutor =
                    new ScheduledThreadPoolExecutor(threads,
                            new TaskThreadFactory("Catalina-utility-", 
                            utilityThreadsAsDaemon, Thread.MIN_PRIORITY));
            scheduledThreadPoolExecutor.setKeepAliveTime(10, 
                    TimeUnit.SECONDS);
            scheduledThreadPoolExecutor.setRemoveOnCancelPolicy(true);
            scheduledThreadPoolExecutor
                .setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
            utilityExecutor = scheduledThreadPoolExecutor;
            // 封装成Tomcat实现的线程池
            utilityExecutorWrapper = 
                    new org.apache.tomcat.util.threads
                            .ScheduledThreadPoolExecutor(utilityExecutor);
        }
    }
    @Override
    protected void startInternal() throws LifecycleException {
        // 执行到这里的时候代表server、service、host、context、wrapper等
        // 组件的init方法已经全部被执行,也就是说必要组件已经全部初始化完成
        fireLifecycleEvent(CONFIGURE_START_EVENT, null);
        // 设置状态为启动中
        setState(LifecycleState.STARTING);
        globalNamingResources.start();
        // 依次调用server中service的start方法
        synchronized (servicesLock) {
            for (int i = 0; i < services.length; i++) {
                services[i].start();
            }
        }
        // monitorFuture是个监听器线程任务,会监听当前状态
        if (periodicEventDelay > 0) {
            monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
                    new Runnable() {
                        @Override
                        public void run() {
                            startPeriodicLifecycleEvent();
                        }
                    }, 0, 60, TimeUnit.SECONDS);
        }
    }
}

1.2.4 StandardService

其部分关键源码如下:

public class StandardService extends LifecycleMBeanBase 
        implements Service {
    private Server server = null;
    // service下有多个Connector核心组件
    protected Connector connectors[] = new Connector[0];
    private final Object connectorsLock = new Object();
    // service下只有一个Container核心组件,Engine就是Container的最顶层对象
    private Engine engine = null;
    protected final ArrayList<Executor> executors = new ArrayList<>();
    @Override
    protected void initInternal() throws LifecycleException {
        super.initInternal();
        // Engine对象即是对Service暴露的Container,前面说过,这个实际上是
        // Container树状结构的ROOT节点,后续分析Container组件时再详细分析
        if (engine != null) {
            engine.init();
        }
        // 初始化各个executor,正常流程下这个是为空的,暂时不清楚其作用
        for (Executor executor : findExecutors()) {
            if (executor instanceof JmxEnabled) {
                ((JmxEnabled) executor).setDomain(getDomain());
            }
            executor.init();
        }
        // 初始化mapperListener,实际上调用的是LifecycleMBeanBase中的
        // initInternal方法,其并没有重写initInternal
        mapperListener.init();
        // 依次分别初始化Connector组件,在Springboot中实际上只有一个
        // Connector对象,即在Tomcat工厂获取Tomcat时初始化的那个Connector
        synchronized (connectorsLock) {
            for (Connector connector : connectors) {
                connector.init();
            }
        }
    }
    @Override
    protected void startInternal() throws LifecycleException {
        setState(LifecycleState.STARTING);
        // 调用Engine的start方法,开始执行Container组件
        if (engine != null) {
            synchronized (engine) {
                engine.start();
            }
        }
        synchronized (executors) {
            for (Executor executor: executors) {
                executor.start();
            }
        }
        // 执行start方法,在这里面将会设置mapper的defaultHostName,即Engine的
        // hostName;这里面也会把Wrapper这些一次方法到context中,形成对应关系
        mapperListener.start();
        // 开始执行Connector的start方法
        synchronized (connectorsLock) {
            for (Connector connector: connectors) {
                if (connector.getState() != LifecycleState.FAILED) {
                    connector.start();
                }
            }
        }
    }
}

1.3 Container组件初始化

1.3.1 Container接口及ContainerBase实现类

在分析Container的初始化流程前我们先看下Container接口以及ContainerBase实现子类源码,这两个类和接下来的Container组件实现类都有关系,因此先了解这两个类的作用是很重要的。

public interface Container extends Lifecycle {
    public static final String ADD_CHILD_EVENT = "addChild";
    public static final String ADD_VALVE_EVENT = "addValve";
    public static final String REMOVE_CHILD_EVENT = "removeChild";
    public static final String REMOVE_VALVE_EVENT = "removeValve";
    public Pipeline getPipeline();
    public Container getParent();
    public void setParent(Container container);
    public void addChild(Container child);
    public Container findChild(String name);
    public Container[] findChildren();
    public void removeChild(Container child);
}

代码只列出了几个重要方法,分别是Container操作树相关的方法以及获得重要的Pipeline对象,这个对象的主要作用便是为完成各个Container直接通信建立对应的通信管道。

接下来看到ContainerBase实现类部分关键源码:

public abstract class ContainerBase extends LifecycleMBeanBase
        implements Container {
    // 当没有权限添加child时使用该内部类添加
    protected class PrivilegedAddChild implements PrivilegedAction<Void> {
        private final Container child;
        PrivilegedAddChild(Container child) {
            this.child = child;
        }
        @Override
        public Void run() {
            // 调用内部方法来添加child
            addChildInternal(child);
            return null;
        }
    }
    // 子节点
    protected final HashMap<String, Container> children = new HashMap<>();
    // 父节点
    protected Container parent = null;
    // 各个Container之间的通信管道,初始化时便已经和Container绑定在了一起
    protected final Pipeline pipeline = new StandardPipeline(this);
    // 等下执行子节点start方法时的线程池
    private int startStopThreads = 1;
    protected ExecutorService startStopExecutor;
    @Override
    public void addChild(Container child) {
        if (Globals.IS_SECURITY_ENABLED) {
            // 没有权限则调用内部类添加child
            PrivilegedAction<Void> dp =
                new PrivilegedAddChild(child);
            AccessController.doPrivileged(dp);
        } else {
            addChildInternal(child);
        }
    }
    private void addChildInternal(Container child) {
        synchronized(children) {
            if (children.get(child.getName()) != null)
                throw new IllegalArgumentException(
                        sm.getString("containerBase.child.notUnique", 
                        child.getName()));
            child.setParent(this);
            children.put(child.getName(), child);
        }
        fireContainerEvent(ADD_CHILD_EVENT, child);
        // 添加完child,如果child的状态为STARTING_PREP,则调用child的start方法
        try {
            if ((getState().isAvailable() ||
                    LifecycleState.STARTING_PREP.equals(getState())) &&
                    startChildren) {
                child.start();
            }
        } catch (LifecycleException e) {
            throw new IllegalStateException(
                    sm.getString("containerBase.child.start"), e);
        }
    }
    @Override
    protected void initInternal() throws LifecycleException {
        // 注册线程池
        reconfigureStartStopExecutor(getStartStopThreads());
        super.initInternal();
    }
    @Override
    protected synchronized void startInternal() throws LifecycleException {
        // 前面的不用管,一般用不到
        ...
        // 拿出所有子节点,依次放入线程池,StartChild内部类将会调用child的
        // 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])));
        }
        // 中间会获取线程池调用完的结果,不用理会
        ...
        // 调用当前对象中pipeline的start方法,具体执行方法流程后面分析
        if (pipeline instanceof Lifecycle) {
            ((Lifecycle) pipeline).start();
        }
        // 设置启动中
        setState(LifecycleState.STARTING);
        // JMX监听器
        if (backgroundProcessorDelay > 0) {
            monitorFuture = Container.getService(ContainerBase.this)
                    .getServer()
                    .getUtilityExecutor().scheduleWithFixedDelay(
                            new ContainerBackgroundProcessorMonitor(), 0, 
                            60, TimeUnit.SECONDS);
        }
    }
    private static class StartChild implements Callable<Void> {
        private Container child;
        public StartChild(Container child) {
            this.child = child;
        }
        @Override
        public Void call() throws LifecycleException {
            child.start();
            return null;
        }
    }
}

由于方法流程过长,因此分析说明便写在代码中。后续关于Container的具体实现类直接看到其对应的startInternal方法中即可,因为确定好层级关系后调用入口只会通过start方法进入。

1.3.2 StandardEngine

其关键源码如下:

public class StandardEngine extends ContainerBase implements Engine {
    public StandardEngine() {
        super();
        // 声明engine对象的pipeline对应的valve对象
        pipeline.setBasic(new StandardEngineValve());
        try {
            setJvmRoute(System.getProperty("jvmRoute"));
        } catch(Exception ex) {
            log.warn(sm.getString("standardEngine.jvmRouteFail"));
        }
        backgroundProcessorDelay = 10;
    }
    private Service service = null;
    private String defaultHost = null;
    @Override
    protected void initInternal() throws LifecycleException {
        // 获得realm权限判断对象后几例调用了父类的initInternal方法
        getRealm();
        super.initInternal();
    }
    @Override
    protected synchronized void startInternal() throws LifecycleException {
        // 直接调用父类的start方法
        super.startInternal();
    }
}

1.3.3 StandardHost

其关键源码如下:

public class StandardHost extends ContainerBase implements Host {
    public StandardHost() {
        super();
        // 依旧老样子,在这里面声明pipeline对应的valve
        pipeline.setBasic(new StandardHostValve());
    }
    private String appBase = "webapps";
    private volatile File appBaseFile = null;
    private String xmlBase = null;
    private volatile File hostConfigBase = null;
    private String configClass =
            "org.apache.catalina.startup.ContextConfig";
    private String errorReportValveClass =
            "org.apache.catalina.valves.ErrorReportValve";
    @Override
    protected synchronized void startInternal() throws LifecycleException {
        // 获得errorReportValveClass值
        // 即对应org.apache.catalina.valves.ErrorReportValve
        String errorValve = getErrorReportValveClass();
        if ((errorValve != null) && (!errorValve.equals(""))) {
            try {
                boolean found = false;
                Valve[] valves = getPipeline().getValves();
                // 先判断已有valve中是否含有该类,如果有则退出,没有则继续下一步
                for (Valve valve : valves) {
                    if (errorValve.equals(valve.getClass().getName())) {
                        found = true;
                        break;
                    }
                }
                if(!found) {
                    // 如果没有找到则将类路径对应的类实例化,并添加进valve链中
                    Valve valve =
                        (Valve) Class.forName(errorValve)
                                .getConstructor().newInstance();
                    getPipeline().addValve(valve);
                }
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                log.error(sm.getString(
                        "standardHost.invalidErrorReportValveClass",
                        errorValve), t);
            }
        }
        super.startInternal();
    }
}

对于StandardHost在初始化及启动流程来看,其只做了确保StandardHost对应的pipeline中含有ErrorReportValve阈值对象。当然configClass属性值org.apache.catalina.startup.ContextConfig对应的ContextConfig也是非常重要的,这个类是一个监听器类,在这里面会完成web.xml文件的读取,即WEB程序中的webapps读取。Springboot初始化启动不需要读取web.xml文件,因此便略过。

1.3.4 TomcatEmbeddedContext

在传统的web程序中,这里应该调用的是StandardContext类,但是奈何Springboot自己实现了一个TomcatEmbeddedContext,并将其添加进了Host中。因此先看到该类的部分源码:

class TomcatEmbeddedContext extends StandardContext {
    @Override
    public boolean loadOnStartup(Container[] children) {
       // 启动时一定会被加载初始化
       return true;
    }
    public void deferredLoadOnStartup() throws LifecycleException {
       // 这个方法的调用时机在Sprignboot里面的Tomcat调用完start方法后,会接着
       // 在TomcatWebServer中调用performDeferredLoadOnStartup方法
       // 在这个方法中将会调用deferredLoadOnStartup方法
       // 这个的方法主要作用便是获取Context中的Wrapper,然后再调用wrapper对象
       // 的load方法进行servlet的加载
       doWithThreadContextClassLoader(getLoader().getClassLoader(),
             () -> getLoadOnStartupWrappers(findChildren())
             .forEach(this::load));
    }
    private Stream<Wrapper> getLoadOnStartupWrappers(
            Container[] children) {
       // children便是context的wrapper子节点,
       Map<Integer, List<Wrapper>> grouped = new TreeMap<>();
       for (Container child : children) {
          Wrapper wrapper = (Wrapper) child;
          int order = wrapper.getLoadOnStartup();
          if (order >= 0) {
             grouped.computeIfAbsent(order, ArrayList::new);
             grouped.get(order).add(wrapper);
          }
       }
       // 获取完这些wrapper子节点再返回
       return grouped.values().stream().flatMap(List::stream);
    }
    private void load(Wrapper wrapper) {
       try {
          // 刚刚获取的wrapper对象的stream流将会一次调用load方法,接着再调用
          // wrapper对象的load对象进行servlet初始化加载
          wrapper.load();
       }
       catch (ServletException ex) {
          String message = sm.getString("...", getName(), 
                  wrapper.getName());
          if (getComputedFailCtxIfServletStartFails()) {
             throw new WebServerException(message, ex);
          }
          getLogger().error(message, StandardWrapper.getRootCause(ex));
       }
    }
}

看到他的源码我们就能知道实际上这个类和Tomcat官方的实例化并没有什么关系,而是为了搭配自家实现的TomcatWebServer而创建的。所以我们还是得看到StandardContext中去看看Tomcat初始化加载时做了什么。

1.3.5 StandardContext

其关键源码如下:

public class StandardContext extends ContainerBase
        implements Context, NotificationEmitter {
    public StandardContext() {
        super();
        // 继续设置对应pipeline的valve
        pipeline.setBasic(new StandardContextValve());
        broadcaster = new NotificationBroadcasterSupport();
        if (!Globals.STRICT_SERVLET_COMPLIANCE) {
            // 添加jsp类型
            resourceOnlyServlets.add("jsp");
        }
    }
    // ServletContainer初始化时将会调用的接口
    private Map<ServletContainerInitializer,Set<Class<?>>> initializers =
            new LinkedHashMap<>();
    protected ApplicationContext context = null;
    @Override
    protected void initInternal() throws LifecycleException {
        super.initInternal();
        ...
        // 发布j2ee.object.created通知
        if (this.getObjectName() != null) {
            Notification notification = 
                    new Notification("j2ee.object.created",
                    this.getObjectName(), 
                    sequenceNumber.getAndIncrement());
            broadcaster.sendNotification(notification);
        }
    }
    @Override
    protected synchronized void startInternal() throws LifecycleException {
        // 当看到initInternal方法只有短短几行时就知道了startInternal方法不简单
        // 这个方法很长,因此我们只针对性的留一些关键方法进行分析
        ...
        boolean ok = true;
        ...
        // 工作目录,即创建Tomcat临时目录中的目录路径
        postWorkDirectory();
        ...
        try {
            if (ok) {
                // 这里获得的loader会是WebappClassLoader对象
                // 在这里面将会完成classes和lib的读取
                Loader loader = getLoader();
                if (loader instanceof Lifecycle) {
                    ((Lifecycle) loader).start();
                }
                ...
                // 获取Context子类,即Wrapper
                for (Container child : findChildren()) {
                    if (!child.getState().isAvailable()) {
                        child.start();
                    }
                }
                // 执行pipeline的start方法
                if (pipeline instanceof Lifecycle) {
                    ((Lifecycle) pipeline).start();
                }
                ...
            }
            ...
            // 熟悉的ServletContainerInitializers接口调用,这里的对象将是
            // TomcatStarter,在Tomcat工厂中添加到context中的
            // 其里面将会调用Spring的ServletContextInitializer接口
            // 来完成某些特定的功能,如DispatcherServlet的动态注册
            for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> 
                    entry : initializers.entrySet()) {
                try {
                    entry.getKey().onStartup(entry.getValue(),
                            getServletContext());
                } catch (ServletException e) {
                    ok = false;
                    break;
                }
            }
            // 这里面将会调用Servlet包中的ServletContextListener接口
            // Spring的web.xml配置便是使用该接口调用进Spring工厂刷新的
            if (ok) {
                if (!listenerStart()) {
                    ok = false;
                }
            }
            // 在这里面配置Tomcat官方过滤器和自己实现的过滤器
            if (ok) {
                if (!filterStart()) {
                    ok = false;
                }
            }
            // 判断wrapper封装的servlet是否是延迟加载,如果是延迟加载则在这里面
            // 不进行操作,如果非延迟加载则在这里面完成servlet的初始化加载
            // 当然,springboot自己实现的TomcatEmbeddedContext直接返回的true
            if (ok) {
                if (!loadOnStartup(findChildren())){
                    log.error(sm.getString("standardContext.servletFail"));
                    ok = false;
                }
            }
            // 开始ContainerBackgroundProcessor线程
            super.threadStart();
        } finally {
            unbindThread(oldCCL);
        }
        // 清空资源句柄
        getResources().gc();
        // 根据ok对象参数设置状态
        if (!ok) {
            setState(LifecycleState.FAILED);
        } else {
            setState(LifecycleState.STARTING);
        }
    }
}

1.3.6 StandardWrapper

其部分关键源码如下:

public class StandardWrapper extends ContainerBase
        implements ServletConfig, Wrapper, NotificationEmitter {
    protected static final String[] DEFAULT_SERVLET_METHODS = 
            new String[] {"GET", "HEAD", "POST" };
    public StandardWrapper() {
        super();
        // 喜闻乐见
        swValve = new StandardWrapperValve();
        pipeline.setBasic(swValve);
        broadcaster = new NotificationBroadcasterSupport();
    }
    protected final StandardWrapperFacade facade = 
            new StandardWrapperFacade(this);
    protected volatile Servlet instance = null;
    protected volatile boolean instanceInitialized = false;
    protected int loadOnStartup = -1;
    protected StandardWrapperValve swValve;
    @Override
    protected synchronized void startInternal() throws LifecycleException {
        ...
        // Start up this component
        super.startInternal();
        setAvailable(0L);
        ...
    }
    @Override
    public synchronized void load() throws ServletException {
        // 这个方法在初始化ServletWrapper的时候将会被调用
        // 先加载获得servlet实例对象
        instance = loadServlet();
        if (!instanceInitialized) {
            // 再将对象初始化
            initServlet(instance);
        }
        ...
    }
    public synchronized Servlet loadServlet() throws ServletException {
        // 如果不为空则代表原来已经加载过了
        if (!singleThreadModel && (instance != null))
            return instance;
        ...
        Servlet servlet;
        try {
            long t1=System.currentTimeMillis();
            if (servletClass == null) {
                unavailable(null);
                throw new ServletException
                    (sm.getString("standardWrapper.notClass", getName()));
            }
            InstanceManager instanceManager = 
                    ((StandardContext)getParent()).getInstanceManager();
            try {
                // 使用获得的servletClass类实例化一个Servlet
                servlet = (Servlet) instanceManager
                        .newInstance(servletClass);
            } catch (ClassCastException e) {
                ...
            } catch (Throwable e) {
               ...
            }
            // 容器servlet实例的特殊处理
            if (servlet instanceof ContainerServlet) {
                ((ContainerServlet) servlet).setWrapper(this);
            }
            classLoadTime=(int) (System.currentTimeMillis() -t1);
            if (servlet instanceof SingleThreadModel) {
                if (instancePool == null) {
                    instancePool = new Stack<>();
                }
                singleThreadModel = true;
            }
            // 真正的初始化servlet
            initServlet(servlet);
            fireContainerEvent("load", this);
            loadTime = System.currentTimeMillis() -t1;
        } finally {
            ...
        }
        return servlet;
    }
    private synchronized void initServlet(Servlet servlet)
        throws ServletException {
        // 如果已经被初始化过则不再初始化
        if (instanceInitialized && !singleThreadModel) return;
        // 调用servlet的init方法
        try {
            if( Globals.IS_SECURITY_ENABLED) {
                boolean success = false;
                try {
                    Object[] args = new Object[] { facade };
                    SecurityUtil.doAsPrivilege("init",
                                               servlet,
                                               classType,
                                               args);
                    success = true;
                } finally {
                    if (!success) {
                        
                        SecurityUtil.remove(servlet);
                    }
                }
            } else {
                servlet.init(facade);
            }
            // 成功调用完init方法没抛异常代表初始化成功
            instanceInitialized = true;
        } catch (UnavailableException f) {
            unavailable(f);
            throw f;
        } catch (ServletException f) {
            ...
        } catch (Throwable f) {
            ...
        }
    }
}

END。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值