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

目录

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、付费专栏及课程。

余额充值