正文
ServletWebServerApplicationContext实现了父类AbstractApplicationContext的onRefresh模板方法,在这里进行了拓展创建了Web容器。
- @Override
- protected void onRefresh() {
- super.onRefresh();
- try {
- createWebServer();
- }
- catch (Throwable ex) {
- throw new ApplicationContextException("Unable to start web server", ex);
- }
- }
创建Web服务
- 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服务器工厂
- 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
自动配置类导入进来的。
- @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工厂
- @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服务
- 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体会一下实现)
- 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
- protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
- return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown());
- }
进入TomcatWebServer
构造方法中:
- public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
- Assert.notNull(tomcat, "Tomcat Server must not be null");
- this.tomcat = tomcat;
- this.autoStart = autoStart;
- //初始化服务
- initialize();
- }
初始化TomcatWebServer
- 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
- public void start() throws LifecycleException {
- //创建服务(Server和Service)
- getServer();
- server.start();
- }
启动服务
- 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
- 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
- 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
- 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
- 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
- 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
的方法
- protected void initInternal() throws LifecycleException {
- super.initInternal();
- }
初始化mapperListener
- 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
- 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
- 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
方法:
- 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
:
- 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
启动。分别来看:
- 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启动
只是发布事件和设置状态而已
- protected void startInternal() throws LifecycleException {
- fireLifecycleEvent(CONFIGURE_START_EVENT, null);
- setState(LifecycleState.STARTING);
- }
Service启动
依次启动 Engine
、Executor
、MapperListener
、Connector
- 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
- 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
方法:
- 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
- private static class StartChild implements Callable<Void>
它实现了带返回值的异步多线程接口 Callable
!那里面的核心方法就是 call
:
- public Void call() throws LifecycleException {
- child.start();
- return null;
- }
它在这里初始化 child
,而通过Debug得知 child
的类型是 StandardHost
,故来到 StandardHost
的 start
方法:
- 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
:
- 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
方法,所以不会启动
- synchronized (executors) {
- for (Executor executor: executors) {
- executor.start();
- }
- }
启动MapperListener
接下来启动 MapperListener
:
- 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
。
- // 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()
- @Override
- public void start() {
- //启动Tomcat 容器
- this.webServer.start();
- this.running = true;
- this.applicationContext
- .publishEvent(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
- }
- 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
- 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
中有顺便启动的部分:
- 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
:
- 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
的启动:
- 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
- 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:初始化前的预处理中
以上就是ServletWebServerApplicationContext创建Web容器Tomcat示例的详细内容,更多关于Web容器Tomcat创建的资料请关注w3xue其它相关文章!