目录
1.1 Lifecycle接口及子类LifecycleBase源码作用
1.2.1 TomcatReactiveWebServerFactory
1.3.1 Container接口及ContainerBase实现类
阅读本篇请先看(一)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()方法流程:
- 检测当前对象生命周期是否为NEW,如果不是则进入invalidTransition方法抛出异常,因此进入到init方法时生命周期一定是NEW;
- 设置对象生命周期为INITIALIZING,即初始化中;
- 调用initInternal()方法进行实现子类的内部初始化;
- 成功调用完initInternal()方法后再将对象生命周期设置成INITIALIZED,即初始化完成。
start()方法流程:
- 判断当前对象的生命周期,如果是STARTING_PREP、STARTING或者STARTED三者中的任意一种状态,则代表start方法早就执行过,因此会直接退出;
- 判断生命周期是否属于NEW或者FAILED,如果是这两种状态,则分别调用init方法和stop方法,因此直接调用Lifecycle接口的start方法而跳过init方法也是可以的。如果前面的条件不成立会判断状态是否是INITIALIZED和STOPPED,如果是则抛出异常;
- 设置当前对象的状态为STARTING_PREP;
- 调用子类实现方法startInternal();
- 判断状态是否是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。