时间:2023-03-15来源:系统城装机大师作者:佚名
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); } } |
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(); } |
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 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(); } } } |
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); } |
(注释均已在源码中标注好,小伙伴们对哪一步感兴趣可以借助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); } |
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); } } } |
创建和初始化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 的组件初始化步骤顺序如下:
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); } } |
只是发布事件和设置状态而已
1 2 3 4 |
protected void startInternal() throws LifecycleException { fireLifecycleEvent(CONFIGURE_START_EVENT, null ); setState(LifecycleState.STARTING); } |
依次启动 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(); } } } } |
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有如下组件被调用了 start 方法:
但由于 Executor
没有实现 startInternal
方法,所以不会启动
1 2 3 4 5 |
synchronized (executors) { for (Executor executor: executors) { executor.start(); } } |
接下来启动 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
。
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(); } } } |
启动过程依次启动了如下组件:
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()); } } } |
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中已经刷新过一次,详情:在文章 https://www.jb51.net/article/277946.htm 的 prepareRefresh:初始化前的预处理中
2023-03-18
如何使用正则表达式保留部分内容的替换功能2023-03-18
gulp-font-spider实现中文字体包压缩实践2023-03-18
ChatGPT在前端领域的初步探索最近闲来无事,在自己的小程序里面集成了一个小视频的接口,但是由于小程序对于播放视频的限制,只能用来做一个demo刷视频了,没办法上线体验。小程序播放视频限制最多10个,超出可能...
2023-03-18
Vue.js、React和Angular对比 以下是Vue.js的代码示例: 以下是React的代码示例: 以下是Angular的代码示例:...
2023-03-18