正文
ServletWebServerApplicationContext实现了父类AbstractApplicationContext的onRefresh模板方法,在这里进行了拓展创建了Web容器。
1
2
3
4
5
6
7
8
9
10
|
@Override
protected void onRefresh() {
super .onRefresh();
try {
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException( "Unable to start web server" , ex);
}
}
|
创建Web服务
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
|
private void createWebServer() {
WebServer webServer = this .webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null ) {
//一、获取Web服务器工厂
ServletWebServerFactory factory = getWebServerFactory();
//二、获取Web服务
this .webServer = factory.getWebServer(getSelfInitializer());
//三、注册Bean生命周期(在容器启动和销毁时调用)
getBeanFactory().registerSingleton( "webServerGracefulShutdown" ,
new WebServerGracefulShutdownLifecycle( this .webServer));
getBeanFactory().registerSingleton( "webServerStartStop" ,
new WebServerStartStopLifecycle( this , this .webServer));
}
else if (servletContext != null ) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException( "Cannot initialize servlet context" , ex);
}
}
//四、初始化上下文环境
initPropertySources();
}
|
一、获取Web服务器工厂
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
protected ServletWebServerFactory getWebServerFactory() {
// Use bean names so that we don't consider the hierarchy
//获取Web服务器工厂名称
String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory. class );
if (beanNames.length == 0 ) {
throw new ApplicationContextException( "Unable to start ServletWebServerApplicationContext due to missing "
+ "ServletWebServerFactory bean." );
}
if (beanNames.length > 1 ) {
throw new ApplicationContextException( "Unable to start ServletWebServerApplicationContext due to multiple "
+ "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
}
//从容器中获取Web服务器工厂实例
return getBeanFactory().getBean(beanNames[ 0 ], ServletWebServerFactory. class );
}
|
这里的Web服务器工厂是通过 ServletWebServerFactoryAutoConfiguration 自动配置类导入进来的。
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
59
60
61
62
63
64
65
66
|
@Configuration (proxyBeanMethods = false )
@AutoConfigureOrder (Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass (ServletRequest. class )
//Web启动环境
@ConditionalOnWebApplication (type = Type.SERVLET)
@EnableConfigurationProperties (ServerProperties. class )
//2.1导入Web工厂
@Import ({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar. class ,
ServletWebServerFactoryConfiguration.EmbeddedTomcat. class ,
ServletWebServerFactoryConfiguration.EmbeddedJetty. class ,
ServletWebServerFactoryConfiguration.EmbeddedUndertow. class })
public class ServletWebServerFactoryAutoConfiguration {
//导入Web服务器工厂自定义程序
@Bean
public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
return new ServletWebServerFactoryCustomizer(serverProperties);
}
//如果是Tomcat则导入Tomcat自定义程序
@Bean
@ConditionalOnClass (name = "org.apache.catalina.startup.Tomcat" )
public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(
ServerProperties serverProperties) {
return new TomcatServletWebServerFactoryCustomizer(serverProperties);
}
@Bean
@ConditionalOnMissingFilterBean (ForwardedHeaderFilter. class )
@ConditionalOnProperty (value = "server.forward-headers-strategy" , havingValue = "framework" )
public FilterRegistrationBean<ForwardedHeaderFilter> forwardedHeaderFilter() {
ForwardedHeaderFilter filter = new ForwardedHeaderFilter();
FilterRegistrationBean<ForwardedHeaderFilter> registration = new FilterRegistrationBean<>(filter);
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR);
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
return registration;
}
/**
* Registers a {@link WebServerFactoryCustomizerBeanPostProcessor}. Registered via
* {@link ImportBeanDefinitionRegistrar} for early registration.
*/
public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
private ConfigurableListableBeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (beanFactory instanceof ConfigurableListableBeanFactory) {
this .beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
}
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
if ( this .beanFactory == null ) {
return ;
}
registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor" ,
WebServerFactoryCustomizerBeanPostProcessor. class );
registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor" ,
ErrorPageRegistrarBeanPostProcessor. class );
}
private void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name, Class<?> beanClass) {
if (ObjectUtils.isEmpty( this .beanFactory.getBeanNamesForType(beanClass, true , false ))) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
beanDefinition.setSynthetic( true );
registry.registerBeanDefinition(name, beanDefinition);
}
}
}
}
|
1.1 选择导入Web工厂
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
|
@Configuration
class ServletWebServerFactoryConfiguration {
ServletWebServerFactoryConfiguration() {
}
//1.如果容器中有Servlet,Undertow,SslClientAuthMode就会创建Undertow工厂
@Configuration
@ConditionalOnClass ({Servlet. class , Undertow. class , SslClientAuthMode. class })
@ConditionalOnMissingBean (
value = {ServletWebServerFactory. class },
search = SearchStrategy.CURRENT
)
public static class EmbeddedUndertow {
public EmbeddedUndertow() {
}
@Bean
public UndertowServletWebServerFactory undertowServletWebServerFactory() {
return new UndertowServletWebServerFactory();
}
}
//2.如果容器中有Servlet,Server,Loader就会创建Jetty工厂
@Configuration
@ConditionalOnClass ({Servlet. class , Server. class , Loader. class , WebAppContext. class })
@ConditionalOnMissingBean (
value = {ServletWebServerFactory. class },
search = SearchStrategy.CURRENT
)
public static class EmbeddedJetty {
public EmbeddedJetty() {
}
@Bean
public JettyServletWebServerFactory JettyServletWebServerFactory() {
return new JettyServletWebServerFactory();
}
}
//3.如果容器中有Servlet,Tomcat,UpgradeProtocol就会创建Tomcat工厂
@Configuration
@ConditionalOnClass ({Servlet. class , Tomcat. class , UpgradeProtocol. class })
@ConditionalOnMissingBean (
value = {ServletWebServerFactory. class },
search = SearchStrategy.CURRENT
)
public static class EmbeddedTomcat {
public EmbeddedTomcat() {
}
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
}
}
|
二、getWebServer:获取Web服务
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
|
public static final String DEFAULT_PROTOCOL = "org.apache.coyote.http11.Http11NioProtocol" ;
private String protocol = DEFAULT_PROTOCOL;
public WebServer getWebServer(ServletContextInitializer... initializers) {
Tomcat tomcat = new Tomcat();
// 给嵌入式Tomcat创建一个临时文件夹,用于存放Tomcat运行中需要的文件
File baseDir = ( this .baseDirectory != null ) ? this .baseDirectory : createTempDir( "tomcat" );
tomcat.setBaseDir(baseDir.getAbsolutePath());
// Tomcat核心概念:Connector,默认放入的protocol为NIO模式
Connector connector = new Connector( this .protocol);
// 给Service添加Connector
tomcat.getService().addConnector(connector);
// 执行定制器,修改即将设置到Tomcat中的Connector
customizeConnector(connector);
tomcat.setConnector(connector);
// 关闭热部署(嵌入式Tomcat不存在修改web.xml、war包等情况)
tomcat.getHost().setAutoDeploy( false );
// 设置backgroundProcessorDelay机制
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this .additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
// 2.1 创建TomcatEmbeddedContext
prepareContext(tomcat.getHost(), initializers);
// 2.2. 创建TomcatWebServer
return getTomcatWebServer(tomcat);
}
|
2.1 创建TomcatEmbeddedContext
(注释均已在源码中标注好,小伙伴们对哪一步感兴趣可以借助IDE自己动手Debug体会一下实现)
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
|
protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
File documentRoot = getValidDocumentRoot();
// 创建TomcatEmbeddedContext
TomcatEmbeddedContext context = new TomcatEmbeddedContext();
if (documentRoot != null ) {
context.setResources( new LoaderHidingResourceRoot(context));
}
context.setName(getContextPath());
context.setDisplayName(getDisplayName());
// 设置contextPath,很熟悉了
context.setPath(getContextPath());
// 给嵌入式Tomcat创建docbase的临时文件夹
File docBase = (documentRoot != null ) ? documentRoot : createTempDir( "tomcat-docbase" );
context.setDocBase(docBase.getAbsolutePath());
// 注册监听器
context.addLifecycleListener( new FixContextListener());
context.setParentClassLoader(( this .resourceLoader != null ) ? this .resourceLoader.getClassLoader()
: ClassUtils.getDefaultClassLoader());
// 设置默认编码映射
resetDefaultLocaleMapping(context);
addLocaleMappings(context);
context.setUseRelativeRedirects( false );
try {
context.setCreateUploadTargets( true );
}
catch (NoSuchMethodError ex) {
// Tomcat is < 8.5.39. Continue.
}
configureTldSkipPatterns(context);
// 自定义的类加载器,可以加载web应用的jar包
WebappLoader loader = new WebappLoader(context.getParentClassLoader());
loader.setLoaderClass(TomcatEmbeddedWebappClassLoader. class .getName());
// 指定类加载器遵循双亲委派机制
loader.setDelegate( true );
context.setLoader(loader);
// 注册默认的Servlet
if (isRegisterDefaultServlet()) {
addDefaultServlet(context);
}
// 如果需要jsp支持,注册jsp的Servlet和Initializer
if (shouldRegisterJspServlet()) {
addJspServlet(context);
addJasperInitializer(context);
}
// 注册监听器
context.addLifecycleListener( new StaticResourceConfigurer(context));
ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);
host.addChild(context);
configureContext(context, initializersToUse);
postProcessContext(context);
}
|
2.2. 创建TomcatWebServer
1
2
3
|
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
return new TomcatWebServer(tomcat, getPort() >= 0 , getShutdown());
}
|
进入 TomcatWebServer 构造方法中:
1
2
3
4
5
6
7
|
public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
Assert.notNull(tomcat, "Tomcat Server must not be null" );
this .tomcat = tomcat;
this .autoStart = autoStart;
//初始化服务
initialize();
}
|
初始化TomcatWebServer
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
|
private void initialize() throws WebServerException {
logger.info( "Tomcat initialized with port(s): " + getPortsDescription( false ));
synchronized ( this .monitor) {
try {
//设置Engine的id
addInstanceIdToEngineName();
//获取Context(TomcatEmbeddedContext 2.1中创建出来的)
Context context = findContext();
//添加监听器 TomcatEmbeddedContext
//在服务启动时如果有连接进来先删除连接,以便在启动服务时不会发生协议绑定。
context.addLifecycleListener((event) -> {
if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) {
// Remove service connectors so that protocol binding doesn't
// happen when the service is started.
//删除ServiceConnectors,以便在启动服务时不会发生协议绑定。
removeServiceConnectors();
}
});
// Start the server to trigger initialization listeners
//2.2.1 启动Tomcat
this .tomcat.start();
// We can re-throw failure exception directly in the main thread
//Tomcat启动有异常需要在主线程中抛出
rethrowDeferredStartupExceptions();
try {
ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
}
catch (NamingException ex) {
// Naming is not enabled. Continue
}
// Unlike Jetty, all Tomcat threads are daemon threads. We create a
// blocking non-daemon to stop immediate shutdown
//开启阻塞非守护线程停止web容器
startDaemonAwaitThread();
}
catch (Exception ex) {
stopSilently();
destroySilently();
throw new WebServerException( "Unable to start embedded Tomcat" , ex);
}
}
}
|
2.2.1 启动Tomcat
创建和初始化Server和Service
1
2
3
4
5
|
public void start() throws LifecycleException {
//创建服务(Server和Service)
getServer();
server.start();
}
|
启动服务
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
|
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)) {
//2.2.1.1 初始化服务
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 );
//2.2.1.2 启动Internal
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());
}
}
|
2.2.1.1 初始化Server
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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, "lifecycleBase.initFail" , toString());
}
}
|
初始化 Server
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
|
protected void initInternal() throws LifecycleException {
//调用父类初始化(设置名称:Tomcat,类型:Server)
super .initInternal();
// Initialize utility executor
reconfigureUtilityExecutor(getUtilityThreadsInternal(utilityThreads));
//注册线程池
register(utilityExecutor, "type=UtilityExecutor" );
// Register global String cache
// Note although the cache is global, if there are multiple Servers
// present in the JVM (may happen when embedding) then the same cache
// will be registered under multiple names
//注册字符串缓存
onameStringCache = register( new StringCache(), "type=StringCache" );
// Register the MBeanFactory
MBeanFactory factory = new MBeanFactory();
factory.setContainer( this );
//注册Bean工厂
onameMBeanFactory = register(factory, "type=MBeanFactory" );
// Register the naming resources
//注册命名资源
globalNamingResources.init();
// Populate the extension validator with JARs from common and shared
// class loaders
if (getCatalina() != null ) {
ClassLoader cl = getCatalina().getParentClassLoader();
// Walk the class loader hierarchy. Stop at the system class loader.
// This will add the shared (if present) and common class loaders
while (cl != null && cl != ClassLoader.getSystemClassLoader()) {
if (cl instanceof URLClassLoader) {
URL[] urls = ((URLClassLoader) cl).getURLs();
for (URL url : urls) {
if (url.getProtocol().equals( "file" )) {
try {
File f = new File (url.toURI());
if (f.isFile() &&
f.getName().endsWith( ".jar" )) {
ExtensionValidator.addSystemResource(f);
}
} catch (URISyntaxException e) {
// Ignore
} catch (IOException e) {
// Ignore
}
}
}
}
cl = cl.getParent();
}
}
// Initialize our defined Services
//2.2.1.1.1 初始化service(2.2.1最开始时创建)
for (Service service : services) {
service.init();
}
}
|
初始化Service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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, "lifecycleBase.initFail" , toString());
}
}
|
初始化Service
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
|
protected void initInternal() throws LifecycleException {
//调用父类初始化(设置名称:Tomcat,类型:Server)
super .initInternal();
//2.2.1.1.1.1 初始化engine
if (engine != null ) {
engine.init();
}
// Initialize any Executors
//2.2.1.1.1.2 初始化executor
for (Executor executor : findExecutors()) {
if (executor instanceof JmxEnabled) {
((JmxEnabled) executor).setDomain(getDomain());
}
executor.init();
}
// Initialize mapper listener
//2.2.1.1.1.3 初始化mapperListener
mapperListener.init();
// Initialize our defined Connectors
//2.2.1.1.1.4 初始化connector
synchronized (connectorsLock) {
for (Connector connector : connectors) {
connector.init();
}
}
}
|
初始化engine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
protected void initInternal() throws LifecycleException {
// Ensure that a Realm is present before any attempt is made to start
// one. This will create the default NullRealm if necessary.
// 在尝试启动一个Realm之前,请确保存在一个Realm。如有必要,这将创建默认的NullRealm
getRealm();
super .initInternal();
}
public Realm getRealm() {
Realm configured = super .getRealm();
// If no set realm has been called - default to NullRealm
// This can be overridden at engine, context and host level
if (configured == null ) {
configured = new NullRealm();
this .setRealm(configured);
}
return configured;
}
|
初始化executor
它还是调的父类 LifecycleMBeanBase 的方法
1
2
3
|
protected void initInternal() throws LifecycleException {
super .initInternal();
}
|
初始化mapperListener
1
2
3
4
5
6
7
8
|
protected void initInternal() throws LifecycleException {
// If oname is not null then registration has already happened via preRegister().
// 如果oname不为null,则已经通过preRegister()进行了注册
if (oname == null ) {
mserver = Registry.getRegistry( null , null ).getMBeanServer();
oname = register( this , getObjectNameKeyProperties());
}
}
|
初始化connector
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
|
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 {
//2.2.1.1.1.5 初始化protocolHandler
protocolHandler.init();
} catch (Exception e) {
throw new LifecycleException(
sm.getString( "coyoteConnector.protocolHandlerInitializationFailed" ), e);
}
}
|
初始化protocolHandler
1
2
3
4
5
6
7
8
9
10
|
public void init() throws Exception {
// Upgrade protocols have to be configured first since the endpoint
// init (triggered via super.init() below) uses this list to configure
// the list of ALPN protocols to advertise
// 必须先配置升级协议,因为端点初始化(通过下面的super.init()触发)使用此列表来配置要发布的ALPN协议列表
for (UpgradeProtocol upgradeProtocol : upgradeProtocols) {
configureUpgradeProtocol(upgradeProtocol);
}
super .init();
}
|
Debug发现这个 upgradeProtocols 为空,直接走下面父类( AbstractProtocol )的 init 方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public void init() throws Exception {
if (getLog().isInfoEnabled()) {
getLog().info(sm.getString( "abstractProtocolHandler.init" , getName()));
logPortOffset();
}
if (oname == null ) {
// Component not pre-registered so register it
oname = createObjectName();
if (oname != null ) {
Registry.getRegistry( null , null ).registerComponent( this , oname, null );
}
}
if ( this .domain != null ) {
rgOname = new ObjectName(domain + ":type=GlobalRequestProcessor,name=" + getName());
Registry.getRegistry( null , null ).registerComponent(
getHandler().getGlobal(), rgOname, null );
}
String endpointName = getName();
endpoint.setName(endpointName.substring( 1 , endpointName.length()- 1 ));
endpoint.setDomain(domain);
//2.2.1.1.1.6 初始化endpoint
endpoint.init();
}
|
上面又是一堆初始化,这个咱暂且不关注,注意最底下有一个 endpoint.init :
初始化endpoint
来到 AbstractEndPoint :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
public final void init() throws Exception {
// Debug为false
if (bindOnInit) {
bindWithCleanup();
bindState = BindState.BOUND_ON_INIT;
}
if ( this .domain != null ) {
// Register endpoint (as ThreadPool - historical name)
oname = new ObjectName(domain + ":type=ThreadPool,name=" " + getName() + " "" );
Registry.getRegistry( null , null ).registerComponent( this , oname, null );
ObjectName socketPropertiesOname = new ObjectName(domain +
":type=ThreadPool,name=" " + getName() + " ",subType=SocketProperties" );
socketProperties.setObjectName(socketPropertiesOname);
Registry.getRegistry( null , null ).registerComponent(socketProperties, socketPropertiesOname, null );
for (SSLHostConfig sslHostConfig : findSslHostConfigs()) {
registerJmx(sslHostConfig);
}
}
}
|
这里面又是初始化 oname ,又是配置 socketProperties 的,但这里面再也没见到 init 方法,证明这部分初始化过程已经结束了。
初始化小结
嵌入式 Tomcat 的组件初始化步骤顺序如下:
Server Service Engine Executor MapperListener Connector Protocol EndPointstartInternal:启动Internal
startInternal 方法中有两部分启动: globalNamingResources 启动, services 启动。分别来看:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
protected void startInternal() throws LifecycleException {
// 发布启动事件
fireLifecycleEvent(CONFIGURE_START_EVENT, null );
setState(LifecycleState.STARTING);
// 2.2.1.2.1 NamingResources启动
globalNamingResources.start();
// Start our defined Services
synchronized (servicesLock) {
for ( int i = 0 ; i < services.length; i++) {
// 2.2.1.2.2 Service启动
services[i].start();
}
}
if (periodicEventDelay > 0 ) {
monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
new Runnable() {
@Override
public void run() {
startPeriodicLifecycleEvent();
}
}, 0 , 60 , TimeUnit.SECONDS);
}
}
|
NamingResources启动
只是发布事件和设置状态而已
1
2
3
4
|
protected void startInternal() throws LifecycleException {
fireLifecycleEvent(CONFIGURE_START_EVENT, null );
setState(LifecycleState.STARTING);
}
|
Service启动
依次启动 Engine 、 Executor 、 MapperListener 、 Connector
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
|
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) {
// 2.2.1.2.2.1 启动Engine
engine.start();
}
}
synchronized (executors) {
for (Executor executor: executors) {
// 2.2.1.2.2.3 启动Executor
executor.start();
}
}
// 2.2.1.2.2.4 启动MapperListener
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) {
// 2.2.1.2.2.5 启动connector
connector.start();
}
}
}
}
|
启动Engine
1
2
3
4
5
6
7
8
|
protected synchronized void startInternal() throws LifecycleException {
// Log our server identification information
if (log.isInfoEnabled()) {
log.info(sm.getString( "standardEngine.start" , ServerInfo.getServerInfo()));
}
// Standard container startup
super .startInternal();
}
|
它直接调的父类 ContainerBase 的 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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
protected synchronized void startInternal() throws LifecycleException {
// Start our subordinate components, if any
logger = null ;
getLogger();
// Cluster与集群相关,SpringBoot项目中使用嵌入式Tomcat,不存在集群
Cluster cluster = getClusterInternal();
if (cluster instanceof Lifecycle) {
((Lifecycle) cluster).start();
}
// Realm与授权相关
Realm realm = getRealmInternal();
if (realm instanceof Lifecycle) {
((Lifecycle) realm).start();
}
// Start our child containers, if any
// Container的类型是StandardHost
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for ( int i = 0 ; i < children.length; i++) {
//异步初始化Host
results.add(startStopExecutor.submit( new StartChild(children[i])));
}
MultiThrowable multiThrowable = null ;
for (Future<Void> result : results) {
try {
result.get();
} catch (Throwable e) {
log.error(sm.getString( "containerBase.threadedStartFailed" ), e);
if (multiThrowable == null ) {
multiThrowable = new MultiThrowable();
}
multiThrowable.add(e);
}
}
if (multiThrowable != null ) {
throw new LifecycleException(sm.getString( "containerBase.threadedStartFailed" ),
multiThrowable.getThrowable());
}
// Start the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle) {
((Lifecycle) pipeline).start();
}
setState(LifecycleState.STARTING);
// Start our thread
if (backgroundProcessorDelay > 0 ) {
monitorFuture = Container.getService(ContainerBase. this ).getServer()
.getUtilityExecutor().scheduleWithFixedDelay(
new ContainerBackgroundProcessorMonitor(), 0 , 60 , TimeUnit.SECONDS);
}
}
|
StartChild 实现了带返回值的异步多线程接口 Callable 核心方法就是在 call
1
|
private static class StartChild implements Callable<Void>
|
它实现了带返回值的异步多线程接口 Callable !那里面的核心方法就是 call :
1
2
3
4
|
public Void call() throws LifecycleException {
child.start();
return null ;
}
|
它在这里初始化 child ,而通过Debug得知 child 的类型是 StandardHost ,故来到 StandardHost 的 start 方法:
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
|
protected synchronized void startInternal() throws LifecycleException {
// Set error report valve
String errorValve = getErrorReportValveClass();
if ((errorValve != null ) && (!errorValve.equals( "" ))) {
try {
boolean found = false ;
Valve[] valves = getPipeline().getValves();
for (Valve valve : valves) {
if (errorValve.equals(valve.getClass().getName())) {
found = true ;
break ;
}
}
if (!found) {
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();
}
|
上面的一个大if结构是设置错误提示页面的,下面又调父类的 startInternal :
1
2
3
4
5
6
7
8
|
protected synchronized void startInternal() throws LifecycleException {
// ......
// Start our child containers, if any
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])));
}
|
又回来了。。。因为一个 Host 包含一个 Context 。
Host 搜索children就会搜到它下面的 Context ,之后又是下面的初始化过程,进入 Context 的初始化:
启动TomcatEmbeddedContext
在TomcatEmbeddedContext有如下组件被调用了 start 方法:
StandardRoot DirResourceSet WebappLoader JarResourceSet StandardWrapper StandardPineline StandardWrapperValve NonLoginAuthenticator StandardContextValve StandardManager LazySessionIdGenerator启动Executor
但由于 Executor 没有实现 startInternal 方法,所以不会启动
1
2
3
4
5
|
synchronized (executors) {
for (Executor executor: executors) {
executor.start();
}
}
|
启动MapperListener
接下来启动 MapperListener :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public void startInternal() throws LifecycleException {
setState(LifecycleState.STARTING);
Engine engine = service.getContainer();
if (engine == null ) {
return ;
}
// 获取当前部署的主机名(本地调试为localhost)
findDefaultHost();
// 把当前自身注册到Engine、Host、Context、Wrapper中
addListeners(engine);
// 取出的Container的类型为Host
Container[] conHosts = engine.findChildren();
for (Container conHost : conHosts) {
Host host = (Host) conHost;
if (!LifecycleState.NEW.equals(host.getState())) {
// Registering the host will register the context and wrappers
//将Host、Context、Wrapper注册到当前监听器中
registerHost(host);
}
}
}
|
启动Connector
最后一步是启动 Connector 。
1
2
3
4
5
6
7
8
9
|
// 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();
}
}
}
|
启动总结
启动过程依次启动了如下组件:
NamingResources Service Engine Host Context Wrapper Executor MapperListener
三、注册Bean生命周期
3.1 WebServerStartStopLifecycle(Web服务器启动-停止生命周期)
WebServerStartStopLifecycle实现了Lifecycle,在容器刷新完成时会调用finishRefresh()
1
2
3
4
5
6
7
8
|
@Override
public void start() {
//启动Tomcat 容器
this .webServer.start();
this .running = true ;
this .applicationContext
.publishEvent( new ServletWebServerInitializedEvent( this .webServer, this .applicationContext));
}
|
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
|
public void start() throws WebServerException {
synchronized ( this .monitor) {
if ( this .started) {
return ;
}
try {
// 3.1.1 还原、启动Connector
addPreviouslyRemovedConnectors();
// 只拿一个Connector
Connector connector = this .tomcat.getConnector();
if (connector != null && this .autoStart) {
// 3.1.2 延迟启动
performDeferredLoadOnStartup();
}
// 检查Connector是否正常启动
checkThatConnectorsHaveStarted();
this .started = true ;
logger.info( "Tomcat started on port(s): " + getPortsDescription( true ) + " with context path '"
+ getContextPath() + "'" );
}
// catch ......
finally {
// 解除ClassLoader与TomcatEmbeddedContext的绑定关系
Context context = findContext();
ContextBindings.unbindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
}
}
}
|
3.1.1 addPreviouslyRemovedConnectors:启动Connector
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
private void addPreviouslyRemovedConnectors() {
Service[] services = this .tomcat.getServer().findServices();
for (Service service : services) {
Connector[] connectors = this .serviceConnectors.get(service);
if (connectors != null ) {
for (Connector connector : connectors) {
// 添加并启动
service.addConnector(connector);
if (! this .autoStart) {
stopProtocolHandler(connector);
}
}
this .serviceConnectors.remove(service);
}
}
}
|
可以发现它将一个缓存区的 Connector 一个一个取出放入 Service 中。注意在 service.addConnector 中有顺便启动的部分:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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
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 ,并与 Service 绑定,之后中间部分的try块,会启动 Connector :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
protected void startInternal() throws LifecycleException {
// Validate settings before starting
if (getPortWithOffset() < 0 ) {
throw new LifecycleException(sm.getString(
"coyoteConnector.invalidPort" , Integer.valueOf(getPortWithOffset())));
}
setState(LifecycleState.STARTING);
try {
// 启动ProtocolHandler
protocolHandler.start();
} catch (Exception e) {
throw new LifecycleException(
sm.getString( "coyoteConnector.protocolHandlerStartFailed" ), e);
}
}
|
Connector 的启动会引发 ProtocolHandler 的启动:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public void start() throws Exception {
if (getLog().isInfoEnabled()) {
getLog().info(sm.getString( "abstractProtocolHandler.start" , getName()));
logPortOffset();
}
// 启动EndPoint
endpoint.start();
monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
new Runnable() {
@Override
public void run() {
if (!isPaused()) {
startAsyncTimeout();
}
}
}, 0 , 60 , TimeUnit.SECONDS);
}
|
ProtocolHandler 的启动会引发 EndPoint 的启动,至此所有组件均已启动完毕。
performDeferredLoadOnStartup:延迟启动
这里面会延迟启动 TomcatEmbeddedContext
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
private void performDeferredLoadOnStartup() {
try {
for (Container child : this .tomcat.getHost().findChildren()) {
if (child instanceof TomcatEmbeddedContext) {
// 延迟启动Context
((TomcatEmbeddedContext) child).deferredLoadOnStartup();
}
}
}
catch (Exception ex) {
if (ex instanceof WebServerException) {
throw (WebServerException) ex;
}
throw new WebServerException( "Unable to start embedded Tomcat connectors" , ex);
}
}
|
四、初始化上下文环境
这里在Spring中已经刷新过一次,详情:在文章的 prepareRefresh:初始化前的预处理中
以上就是ServletWebServerApplicationContext创建Web容器Tomcat示例的详细内容,更多关于Web容器Tomcat创建的资料请关注其它相关文章!
原文链接:https://juejin.cn/post/7208384641190674492
查看更多关于ServletWebServerApplicationContext创建Web容器Tomcat示例的详细内容...