Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

线程池在 Tomcat 中也是非常重要的工具,这里我们简单介绍下 Tomcat 中的线程池,在 container 的启动过程中
org.apache.catalina.core.ContainerBase#initInternal

1
2
3
4
5
@Override
protected void initInternal() throws LifecycleException {
reconfigureStartStopExecutor(getStartStopThreads());
super.initInternal();
}

这里先会获取线程数,

1
2
3
4
@Override
public int getStartStopThreads() {
return startStopThreads;
}

默认的 ContainerBase 的设置线程数是 1

1
private int startStopThreads = 1;

那就会按照 org.apache.catalina.core.ContainerBase#reconfigureStartStopExecutor 来设置线程池类型

1
2
3
4
5
6
7
8
9
10
11
12
13
private void reconfigureStartStopExecutor(int threads) {
if (threads == 1) {
// Use a fake executor
if (!(startStopExecutor instanceof InlineExecutorService)) {
startStopExecutor = new InlineExecutorService();
}
} else {
// Delegate utility execution to the Service
Server server = Container.getService(this).getServer();
server.setUtilityThreads(threads);
startStopExecutor = server.getUtilityExecutor();
}
}

此时线程池类型是 null 也就会走到上一个分支中,new 一个 InlineExecutorService 出来
前面的这些其实是在 StandardEngine 初始化过程中,也就是 initInternal 时候进行的
然后具体的使用是在 startInternal 开始方法中,

1
2
3
4
5
6
// Start our child containers, if any
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for (Container child : children) {
results.add(startStopExecutor.submit(new StartChild(child)));
}

会获取当前 StandardEngine 的子组件提交给线程池进行启动
而这个 StartChild 也比较简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}
}

就是调用子组件的 start 方法,
在 org.apache.tomcat.util.threads.InlineExecutorService 的父类,java.util.concurrent.AbstractExecutorService 中先会把 Callable 包装成 FutureTask

1
2
3
4
5
6
7
8
9
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}

然后进行执行,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
public void execute(Runnable command) {
synchronized (lock) {
if (shutdown) {
throw new RejectedExecutionException();
}
taskRunning = true;
}
command.run();
synchronized (lock) {
taskRunning = false;
if (shutdown) {
terminated = true;
lock.notifyAll();
}
}
}

这个就是我们 startStopExecutor 的主要作用,帮我们启动子组件
对于 Container 来说启动的就是 host,而其实 host 也是继承了 ContainerBase 的,后面可以再继续介绍下


org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#createWebServer 的时候会调用

1
this.webServer = factory.getWebServer(getSelfInitializer());

就会调用到之前说到的

1
2
3
4
5
6
7
8
9
10
11
12
private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {
return this::selfInitialize;
}

private void selfInitialize(ServletContext servletContext) throws ServletException {
prepareWebApplicationContext(servletContext);
registerApplicationScope(servletContext);
WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);
for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
beans.onStartup(servletContext);
}
}

而这里有个
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#getServletContextInitializerBeans
获取初始化所需要的 bean

1
2
3
protected Collection<ServletContextInitializer> getServletContextInitializerBeans() {
return new ServletContextInitializerBeans(getBeanFactory());
}

里面就是 new 了这个 org.springframework.boot.web.servlet.ServletContextInitializerBeans#ServletContextInitializerBeans

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public ServletContextInitializerBeans(ListableBeanFactory beanFactory,
Class<? extends ServletContextInitializer>... initializerTypes) {
this.initializers = new LinkedMultiValueMap<>();
this.initializerTypes = (initializerTypes.length != 0) ? Arrays.asList(initializerTypes)
: Collections.singletonList(ServletContextInitializer.class);
// 这里是添加 ServletContextInitializer
addServletContextInitializerBeans(beanFactory);
// filter 是在这里
addAdaptableBeans(beanFactory);
List<ServletContextInitializer> sortedInitializers = this.initializers.values().stream()
.flatMap((value) -> value.stream().sorted(AnnotationAwareOrderComparator.INSTANCE))
.collect(Collectors.toList());
this.sortedList = Collections.unmodifiableList(sortedInitializers);
logMappings(this.initializers);
}

具体来看看 org.springframework.boot.web.servlet.ServletContextInitializerBeans#addAdaptableBeans

1
2
3
4
5
6
7
8
9
10
11
protected void addAdaptableBeans(ListableBeanFactory beanFactory) {
MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory);
// 这里把 Servlet 作为 RegistrationBean
addAsRegistrationBean(beanFactory, Servlet.class, new ServletRegistrationBeanAdapter(multipartConfig));
// 这里把 Filter 作为 RegistrationBean
addAsRegistrationBean(beanFactory, Filter.class, new FilterRegistrationBeanAdapter());
for (Class<?> listenerType : ServletListenerRegistrationBean.getSupportedTypes()) {
addAsRegistrationBean(beanFactory, EventListener.class, (Class<EventListener>) listenerType,
new ServletListenerRegistrationBeanAdapter());
}
}

里面是这两段逻辑,先从 beanfactory 里获取到该类型的 bean,然后包装成 RegistrationBean,添加到 initializers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
protected <T> void addAsRegistrationBean(ListableBeanFactory beanFactory, Class<T> type,
RegistrationBeanAdapter<T> adapter) {
addAsRegistrationBean(beanFactory, type, type, adapter);
}

private <T, B extends T> void addAsRegistrationBean(ListableBeanFactory beanFactory, Class<T> type,
Class<B> beanType, RegistrationBeanAdapter<T> adapter) {
List<Map.Entry<String, B>> entries = getOrderedBeansOfType(beanFactory, beanType, this.seen);
for (Entry<String, B> entry : entries) {
String beanName = entry.getKey();
B bean = entry.getValue();
if (this.seen.add(bean)) {
// One that we haven't already seen
RegistrationBean registration = adapter.createRegistrationBean(beanName, bean, entries.size());
int order = getOrder(bean);
registration.setOrder(order);
this.initializers.add(type, registration);
if (logger.isTraceEnabled()) {
logger.trace("Created " + type.getSimpleName() + " initializer for bean '" + beanName + "'; order="
+ order + ", resource=" + getResourceDescription(beanName, beanFactory));
}
}
}
}

然后再回到第一段,其中的循环里面,因为 ServletContextInitializerBeans 继承了 AbstractCollection 并且实现了 iterator 接口

1
2
3
for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
beans.onStartup(servletContext);
}

在 for 循环中会把 Initializer 排序后的 sortedList 返回 iterator,也就是前面把 filter 包装成的 RegistrationBean

1
2
3
public Iterator<ServletContextInitializer> iterator() {
return this.sortedList.iterator();
}

然后调用了 onStartup 方法,

1
2
3
4
5
6
7
8
public final void onStartup(ServletContext servletContext) throws ServletException {
String description = getDescription();
if (!isEnabled()) {
logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");
return;
}
register(description, servletContext);
}

就会去执行注册逻辑

Tomcat 中的很多组件都是继承了LifecycleBase这个抽象类的,包括之前讲过的 connector,server,service,context,host 这些组件都是,我们先来看下接口
主体是分为两部分,第一部分是定义状态时间,如 before_init 和 after_init,跟事件监听器的几个方法,添加查询和移除,第二部分是生命周期的相关方法,初始化开始结束与销毁等方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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 addLifecycleListener(LifecycleListener listener);

public LifecycleListener[] findLifecycleListeners();

public void removeLifecycleListener(LifecycleListener listener);

public void init() throws LifecycleException;

public void start() throws LifecycleException;

public void stop() throws LifecycleException;

public void destroy() throws LifecycleException;

public LifecycleState getState();

public String getStateName();


/**
* Marker interface used to indicate that the instance should only be used
* once. Calling {@link #stop()} on an instance that supports this interface
* will automatically call {@link #destroy()} after {@link #stop()}
* completes.
*/
public interface SingleUse {
}
}

对应的就是 Lifecycle 的状态,可以在 LifecycleState 中看到,这个枚举有两个字段组成,available 表示该状态下这个对应的组件状态是否可用,另一个就是对应的事件,比如 INITIALIZING 这个 state 对应的 BEFORE_INIT_EVENT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public enum LifecycleState {
NEW(false, null),
INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),
INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),
STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),
STARTING(true, Lifecycle.START_EVENT),
STARTED(true, Lifecycle.AFTER_START_EVENT),
STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),
STOPPING(false, Lifecycle.STOP_EVENT),
STOPPED(false, Lifecycle.AFTER_STOP_EVENT),
DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),
DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
FAILED(false, null);

private final boolean available;
private final String lifecycleEvent;

private LifecycleState(boolean available, String lifecycleEvent) {
this.available = available;
this.lifecycleEvent = lifecycleEvent;
}

/**
* May the public methods other than property getters/setters and lifecycle
* methods be called for a component in this state? It returns
* <code>true</code> for any component in any of the following states:
* <ul>
* <li>{@link #STARTING}</li>
* <li>{@link #STARTED}</li>
* <li>{@link #STOPPING_PREP}</li>
* </ul>
*
* @return <code>true</code> if the component is available for use,
* otherwise <code>false</code>
*/
public boolean isAvailable() {
return available;
}

public String getLifecycleEvent() {
return lifecycleEvent;
}
}

然后可以看看 Lifecycle 的状态流转示意,下面是从 Lifecycle 的代码注释里拷出来的

Common interface for component life cycle methods. Catalina components may implement this interface (as well as the appropriate interface(s) for the functionality they support) in order to provide a consistent mechanism to start and stop the component. The valid state transitions for components that support Lifecycle are:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
           start()
-----------------------------
| |
| init() |
NEW -»-- INITIALIZING |
| | | | ------------------«-----------------------
| | |auto | | |
| | \|/ start() \|/ \|/ auto auto stop() |
| | INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»--- |
| | | | |
| |destroy()| | |
| --»-----«-- ------------------------«-------------------------------- ^
| | | |
| | \|/ auto auto start() |
| | STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»-----
| \|/ ^ | ^
| | stop() | | |
| | -------------------------- | |
| | | | |
| | | destroy() destroy() | |
| | FAILED ----»------ DESTROYING ---«----------------- |
| | ^ | |
| | destroy() | |auto |
| --------»----------------- \|/ |
| DESTROYED |
| |
| stop() |
----»-----------------------------»------------------------------

Any state can transition to FAILED.

Calling start() while a component is in states STARTING_PREP, STARTING or
STARTED has no effect.

Calling start() while a component is in state NEW will cause init() to be
called immediately after the start() method is entered.

Calling stop() while a component is in states STOPPING_PREP, STOPPING or
STOPPED has no effect.

Calling stop() while a component is in state NEW transitions the component
to STOPPED. This is typically encountered when a component fails to start and
does not start all its sub-components. When the component is stopped, it will
try to stop all sub-components - even those it didn’t start.

Attempting any other transition will throw LifecycleException.

The LifecycleEvents fired during state changes are defined in the methods that trigger the changed. No LifecycleEvents are fired if the attempted transition is not valid.
好的项目就是会把这样的示意图画得很好,把状态流转都画得很明确,而不一定要什么好看的作图工具,用字符就可以
而在 LifecycleBase类中是把更细节的实现了,
init方法就是先判断了状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {
// 只有状态是 new 才可以执行初始化 init
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}

try {
setStateInternal(LifecycleState.INITIALIZING, null, false);
initInternal();
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
handleSubClassException(t, "lifecycleBase.initFail", toString());
}
}

在判断状态后就先设置了初始化中这个状态,这里设置的时候是 check 是 false 的,所以直接到设置状态,并且触发事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
private synchronized void setStateInternal(LifecycleState state, Object data, boolean check)
throws LifecycleException {

if (log.isDebugEnabled()) {
log.debug(sm.getString("lifecycleBase.setState", this, state));
}

if (check) {
// Must have been triggered by one of the abstract methods (assume
// code in this class is correct)
// null is never a valid state
if (state == null) {
invalidTransition("null");
// Unreachable code - here to stop eclipse complaining about
// a possible NPE further down the method
return;
}

// Any method can transition to failed
// startInternal() permits STARTING_PREP to STARTING
// stopInternal() permits STOPPING_PREP to STOPPING and FAILED to
// STOPPING
if (!(state == LifecycleState.FAILED ||
(this.state == LifecycleState.STARTING_PREP &&
state == LifecycleState.STARTING) ||
(this.state == LifecycleState.STOPPING_PREP &&
state == LifecycleState.STOPPING) ||
(this.state == LifecycleState.FAILED &&
state == LifecycleState.STOPPING))) {
// No other transition permitted
invalidTransition(state.name());
}
}

this.state = state;
String lifecycleEvent = state.getLifecycleEvent();
if (lifecycleEvent != null) {
fireLifecycleEvent(lifecycleEvent, data);
}
}

触发事件调用了 fireLifecycleEvent

1
2
3
4
5
6
protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
listener.lifecycleEvent(event);
}
}

会调用所有的 listener 将事件发送出去
而回到上面 init 方法,第二步的 initInternal 就是 Tomcat 的 Lifecycle 中非常核心的一点了
因为上面说到很多组件都是继承了 LifecycleBase 的,实际外部被调用的其实都是 LifecycleBase 的
init,start 等方法,内部是由这个抽象基类去设置前后的状态,以及调用 initInternal ,也就是具体
实现类的实现方法,譬如 connector 的 initInternal 方法,就是真正处理初始化逻辑的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Override
protected void initInternal() throws LifecycleException {

super.initInternal();

if (protocolHandler == null) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerInstantiationFailed"));
}

// Initialize adapter
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter);
if (service != null) {
protocolHandler.setUtilityExecutor(service.getServer().getUtilityExecutor());
}

// Make sure parseBodyMethodsSet has a default
if (null == parseBodyMethodsSet) {
setParseBodyMethods(getParseBodyMethods());
}

if (protocolHandler.isAprRequired() && !AprStatus.isInstanceCreated()) {
throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprListener",
getProtocolHandlerClassName()));
}
if (protocolHandler.isAprRequired() && !AprStatus.isAprAvailable()) {
throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprLibrary",
getProtocolHandlerClassName()));
}
if (AprStatus.isAprAvailable() && AprStatus.getUseOpenSSL() &&
protocolHandler instanceof AbstractHttp11JsseProtocol) {
AbstractHttp11JsseProtocol<?> jsseProtocolHandler =
(AbstractHttp11JsseProtocol<?>) protocolHandler;
if (jsseProtocolHandler.isSSLEnabled() &&
jsseProtocolHandler.getSslImplementationName() == null) {
// OpenSSL is compatible with the JSSE configuration, so use it if APR is available
jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName());
}
}

try {
protocolHandler.init();
} catch (Exception e) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
}
}

start 方法也是类似的,但是更复杂,第一步也是状态判断,是不是已经被启动过了,如果还是 new 状态的话就先调用 init,如果已经 failed 启动失败了就直接调用 stop 结束了,如果是非已初始化和非已停止的状态则是错误的状态转变
如果是正常情况,那就是先设置成 STARTING_PREP,然后调用实现类的 startInternal,如果启动失败了就调用 stop,此时理论上应该是启动中 STARTING 状态,否则就是异常状态转变,剩下的就是状态启动完的状态,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Override
public final synchronized void start() throws LifecycleException {

if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
LifecycleState.STARTED.equals(state)) {

if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
}

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)) {
// This is a 'controlled' failure. The component put itself into the
// FAILED state so call stop() to complete the clean-up.
stop();
} else if (!state.equals(LifecycleState.STARTING)) {
// Shouldn't be necessary but acts as a check that sub-classes are
// doing what they are supposed to.
invalidTransition(Lifecycle.AFTER_START_EVENT);
} else {
setStateInternal(LifecycleState.STARTED, null, false);
}
} catch (Throwable t) {
// This is an 'uncontrolled' failure so put the component into the
// FAILED state and throw an exception.
handleSubClassException(t, "lifecycleBase.startFail", toString());
}
}

stop 跟 destroy 也类似的

在看 Tomcat 代码过程中碰到了一个小问题,可以用代码来举例讲一下
先定义一个简单的接口

1
2
3
4
5
@FunctionalInterface
public interface FunctionalInterfaceTest {

String getInfo();
}

functionalInterface本质还是个接口,所以可以用类实现接口的方式
比如像这样

1
2
3
4
5
6
public class FunctionalInterfaceImpl implements FunctionalInterfaceTest{
@Override
public String getInfo() {
return "info";
}
}

但是有下面另外两种方式也是可以实现接口的
第一种是 lambda,

1
2
FunctionalInterfaceTest interfaceTest = () -> "aaa";
System.out.println(interfaceTest.getInfo());

这个实现方式就是直接把 lambda 表达式作为接口实现,但是如果这样就要注意如果实在代码中间的话,debug 还是会跳到这个 lambda 的实现,有时候会混乱,因为只是跳转到 lambda 表达式,而不是所在的方法
第二种是这样

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
FunctionalInterfaceTest interfaceTest1 = demo.getSelfInfo();
System.out.println(interfaceTest.getInfo());
}

public FunctionalInterfaceTest getSelfInfo() {
return this::info;
}

public String info() {
return "ccc";
}

前面 getSelfInfo 的返回值就是类里的一个方法,可以用来作为 FunctionalInterface 的实现,这里跟上面有个比较奇怪的,或者说对于常规的接口理解,一般来说实现的方法签名必须和接口的方法签名一致,但是对于函数接口,私域就突破了这个限制,不管是lambda 这种匿名函数或者后面这种方法引用,都没有用 getInfo 这个方法名,这也是一个比较最近的一个理解。

这里开始介绍下 Service 的启动过程,Tomcat 的启动过程中

1
2
3
4
public void start() throws LifecycleException {
getServer();
server.start();
}

getServer之前讲到过

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public Server getServer() {

if (server != null) {
return server;
}

System.setProperty("catalina.useNaming", "false");

server = new StandardServer();

initBaseDir();

// Set configuration source
ConfigFileLoader.setSource(new CatalinaBaseConfigurationSource(new File(basedir), null));

server.setPort( -1 );

Service service = new StandardService();
service.setName("Tomcat");
server.addService(service);
return server;
}

会 new 一个StandardService,添加到 server 里,然后进行启动
而这个外面的 server.start 其实调用的是 org.apache.catalina.Lifecycle#start,
里面是一个 Lifecycle 的接口,这个接口被很多 Tomcat 的组件实现,其实都共用了 Lifecycle 的机制
然后 Lifecycle 里面会根据状态,调用实际的实现层的 startInternal 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Override
protected void startInternal() throws LifecycleException {

if(log.isInfoEnabled()) {
log.info(sm.getString("standardService.start.name", this.name));
}
setState(LifecycleState.STARTING);

// Start our defined Container first
if (engine != null) {
synchronized (engine) {
engine.start();
}
}

synchronized (executors) {
for (Executor executor: executors) {
executor.start();
}
}

mapperListener.start();

// Start our defined Connectors second
synchronized (connectorsLock) {
for (Connector connector: connectors) {
// If it has already failed, don't try and start it
if (connector.getState() != LifecycleState.FAILED) {
connector.start();
}
}
}
}

这里会先设置状态,这个状态也有点东西,可以后面再讲,因为里面有个状态事件的触发
然后是启动 Engine,也就是 container,在这里就是 StandardEngine,先不深入去讲里面做了啥,后面讲 StandardEngine 的启动过程会讲,然后是启动线程池了,对于 StandardService 是没有线程池要启动的,或者是 springboot 集成的这个 Tomcat 中不需要,接着就是 mapperListener 的启动,这里其实是给 container 这种添加 listener,用来监听事件,做处理
然后就是启动 connector,connector 的启动就是之前说的,里面会启动 protocolHandler,这里还是一样的通过 Lifecycle 的接口,再通过 Lifecycle 的模板方法调用实际的 connector 实现 startInternal 方法,这也是 Tomcat 的一大特点,关于 Tomcat 也是个很大的课题,后面可能还会调整下组织结构,对新同学更友好一点。
值得注意的还有两个
第一个是添加 connector,先是锁一下,设置 connector 的 Service,然后 connectors 是个数组,这里进行了重新申请一个数组,然后进行拷贝,再把新添加的放到数组最后,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Override
public void addConnector(Connector connector) {

synchronized (connectorsLock) {
connector.setService(this);
Connector results[] = new Connector[connectors.length + 1];
System.arraycopy(connectors, 0, results, 0, connectors.length);
results[connectors.length] = connector;
connectors = results;
}

try {
if (getState().isAvailable()) {
connector.start();
}
} catch (LifecycleException e) {
throw new IllegalArgumentException(
sm.getString("standardService.connector.startFailed", connector), e);
}

// Report this property change to interested listeners
support.firePropertyChange("connector", null, connector);
}

然后是判断当前的状态是否可用,如果可用就启动 connector, 最后触发下 connector 的变更事件
还有一个是设置Engine,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

@Override
public void setContainer(Engine engine) {
Engine oldEngine = this.engine;
if (oldEngine != null) {
oldEngine.setService(null);
}
this.engine = engine;
if (this.engine != null) {
this.engine.setService(this);
}
if (getState().isAvailable()) {
if (this.engine != null) {
try {
this.engine.start();
} catch (LifecycleException e) {
log.error(sm.getString("standardService.engine.startFailed"), e);
}
}
// Restart MapperListener to pick up new engine.
try {
mapperListener.stop();
} catch (LifecycleException e) {
log.error(sm.getString("standardService.mapperListener.stopFailed"), e);
}
try {
mapperListener.start();
} catch (LifecycleException e) {
log.error(sm.getString("standardService.mapperListener.startFailed"), e);
}
if (oldEngine != null) {
try {
oldEngine.stop();
} catch (LifecycleException e) {
log.error(sm.getString("standardService.engine.stopFailed"), e);
}
}
}

// Report this property change to interested listeners
support.firePropertyChange("container", oldEngine, this.engine);
}

前面两步是把第一个的 engine 的 service 设置为 null,然后第二个 engine 也就是新的这个的 service 设置成当前的 service,然后也是判断状态,启动 engine,接着是重启 mapperListener,先关闭再启动,最后是关闭老的 engine,最后的最后就是触发 container 变更事件。

0%