好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

ServletWebServerApplicationContext创建Web容器Tomcat示例

正文

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 &amp;&amp; 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 &gt; 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 &lt; 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) &amp;&amp;
             !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 &amp;&amp; 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() &amp;&amp;
                                     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() &amp;&amp; !AprStatus.isInstanceCreated()) {
         throw new LifecycleException(sm.getString( "coyoteConnector.protocolHandlerNoAprListener" ,
                 getProtocolHandlerClassName()));
     }
     if (protocolHandler.isAprRequired() &amp;&amp; !AprStatus.isAprAvailable()) {
         throw new LifecycleException(sm.getString( "coyoteConnector.protocolHandlerNoAprLibrary" ,
                 getProtocolHandlerClassName()));
     }
     if (AprStatus.isAprAvailable() &amp;&amp; AprStatus.getUseOpenSSL() &amp;&amp;
             protocolHandler instanceof AbstractHttp11JsseProtocol) {
         AbstractHttp11JsseProtocol&lt;?&gt; jsseProtocolHandler =
                 (AbstractHttp11JsseProtocol&lt;?&gt;) protocolHandler;
         if (jsseProtocolHandler.isSSLEnabled() &amp;&amp;
                 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 EndPoint

startInternal:启动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 &lt; services.length; i++) {
             // 2.2.1.2.2 Service启动
             services[i].start();
         }
     }
     if (periodicEventDelay &gt; 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&lt;Future&lt;Void&gt;&gt; results = new ArrayList&lt;&gt;();
     for ( int i = 0 ; i &lt; children.length; i++) {
         //异步初始化Host
         results.add(startStopExecutor.submit( new StartChild(children[i])));
     }
     MultiThrowable multiThrowable = null ;
     for (Future&lt;Void&gt; 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 &gt; 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 ) &amp;&amp; (!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 &amp;&amp; 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() &lt; 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示例的详细内容...

  阅读:18次