日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Spring boot整合tomcat底層原理剖析

瀏覽:229日期:2023-03-19 16:51:50
目錄
  • 本文結(jié)論
  • spring-boot-starter-web內(nèi)部有什么?
  • TomcatServletWebServerFactory的作用:獲取WebServer對(duì)象
  • spring boot啟動(dòng)的時(shí)候啟動(dòng)tomcat
  • 獲取tomcat的配置
  • ServletWebServerFactoryCustomizer這個(gè)Bean是哪里的?

從源碼層面理解spring boot的默認(rèn)web容器,以及他們是如何關(guān)聯(lián)起來(lái)的。

本文結(jié)論

  • 源碼基于spring boot2.6.6
  • 項(xiàng)目的pom.xml中存在spring-boot-starter-web的時(shí)候,在項(xiàng)目啟動(dòng)時(shí)候就會(huì)自動(dòng)啟動(dòng)一個(gè)Tomcat。
  • 自動(dòng)配置類(lèi)ServletWebServerFactoryAutoConfiguration找到系統(tǒng)中的所有web容器。我們以tomcat為主。
  • 構(gòu)建TomcatServletWebServerFactory的bean。
  • SpringBoot的啟動(dòng)過(guò)程中,會(huì)調(diào)用核心的refresh方法,內(nèi)部會(huì)執(zhí)行onRefresh()方法,onRefresh()方法是一個(gè)模板方法,他會(huì)執(zhí)行會(huì)執(zhí)行子類(lèi)ServletWebServerApplicationContext的onRefresh()方法。
  • onRefresh()方法中調(diào)用getWebServer啟動(dòng)web容器。

spring-boot-starter-web內(nèi)部有什么?

  • 在spring-boot-starter-web這個(gè)starter中,其實(shí)內(nèi)部間接的引入了spring-boot-starter-tomcat這個(gè)starter,這個(gè)spring-boot-starter-tomcat又引入了tomcat-embed-core依賴(lài),所以只要我們項(xiàng)目中依賴(lài)了spring-boot-starter-web就相當(dāng)于依賴(lài)了Tomcat。

自動(dòng)配置類(lèi):ServletWebServerFactoryAutoConfiguration在spring-boot-autoconfigure-2.6.6.jar這個(gè)包中的spring.factories文件內(nèi),配置了大量的自動(dòng)配置類(lèi),其中就包括自動(dòng)配置tomcat的自動(dòng)配置類(lèi):ServletWebServerFactoryAutoConfiguration

自動(dòng)配置類(lèi)的代碼如下

// full模式@Configuration(proxyBeanMethods = false)// 配置類(lèi)解析順序@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)// 條件注解:表示項(xiàng)目依賴(lài)中要有ServletRequest類(lèi)(server api)@ConditionalOnClass(ServletRequest.class)// 表示項(xiàng)目應(yīng)用類(lèi)型得是SpringMVC(在啟動(dòng)過(guò)程中獲取的SpringBoot應(yīng)用類(lèi)型)@ConditionalOnWebApplication(type = Type.SERVLET)// 讀取server下的配置文件@EnableConfigurationProperties(ServerProperties.class)// import具體的加載配置的類(lèi)和具體web實(shí)現(xiàn)容器@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,		ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,		ServletWebServerFactoryConfiguration.EmbeddedJetty.class,		ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })public class ServletWebServerFactoryAutoConfiguration {	......}
  • ServletRequest是存在于tomcat-embed-core-9.0.60.jar中的的一個(gè)類(lèi),所以@ConditionalOnClass(ServletRequest.clas s)會(huì)滿足。
  • spring-boot-starter-web中,間接的引入了spring-web、spring-webmvc等依賴(lài),所以@ConditionalOnWebApplication(type = Type.SERVLET)條件滿足。
  • 上面的倆個(gè)條件都滿足,所以spring回去解析這個(gè)配置類(lèi),在解析過(guò)程中會(huì)發(fā)現(xiàn)他import了三個(gè)類(lèi)!我們重點(diǎn)關(guān)注EmbeddedTomcat。其他倆個(gè)的內(nèi)部條件注解不滿足!
@Configuration(proxyBeanMethods = false)// tomcat內(nèi)部的類(lèi),肯定都存在@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })// 程序員如果自定義了ServletWebServerFactory的Bean,那么這個(gè)Bean就不加載。@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)static class EmbeddedTomcat {    @Bean    TomcatServletWebServerFactory tomcatServletWebServerFactory(ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,ObjectProvider<TomcatContextCustomizer> contextCustomizers,ObjectProvider<TomcatProtocolHandlerCustomizer<?>> protocolHandlerCustomizers) {    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();    // orderedStream()調(diào)用時(shí)會(huì)去Spring容器中找到TomcatConnectorCustomizer類(lèi)型的Bean,默認(rèn)是沒(méi)有的,程序員可以自己定義。這個(gè)Bean可以設(shè)置一些tomcat的配置,比如端口、協(xié)議...    // TomcatConnectorCustomizer:是用來(lái)配置Tomcat中的Connector組件的    factory.getTomcatConnectorCustomizers().addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));    // TomcatContextCustomizer:是用來(lái)配置Tomcat中的Context組件的    factory.getTomcatContextCustomizers().addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));    // TomcatProtocolHandlerCustomizer:是用來(lái)配置Tomcat中的ProtocolHandler組件的    factory.getTomcatProtocolHandlerCustomizers().addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));    return factory;}    }}
  • 對(duì)于另外的EmbeddedJetty和EmbeddedUndertow,邏輯類(lèi)似,都是判斷項(xiàng)目依賴(lài)中是否有Jetty和Undertow的依賴(lài),如果有,那么對(duì)應(yīng)在Spring容器中就會(huì)存在JettyServletWebServerFactory類(lèi)型的Bean、或者存在UndertowServletWebServerFactory類(lèi)型的Bean。

TomcatServletWebServerFactory的作用:獲取WebServer對(duì)象

  • TomcatServletWebServerFactory他實(shí)現(xiàn)了ServletWebServerFactory這個(gè)接口。
  • ServletWebServerFactory接口內(nèi)部只有一個(gè)方法是獲取WebServer對(duì)象。

  • WebServer擁有啟動(dòng)、停止、獲取端口等方法,就會(huì)發(fā)現(xiàn)WebServer其實(shí)指的就是Tomcat、Jetty、Undertow。

  • 而TomcatServletWebServerFactory就是用來(lái)生成Tomcat所對(duì)應(yīng)的WebServer對(duì)象,具體一點(diǎn)就是TomcatWebServer對(duì)象,并且在生成TomcatWebServer對(duì)象時(shí)會(huì)把Tomcat給啟動(dòng)起來(lái)。
  • 在源碼中,調(diào)用TomcatServletWebServerFactory對(duì)象的getWebServer()方法時(shí)就會(huì)啟動(dòng)Tomcat。
public WebServer getWebServer(ServletContextInitializer... initializers) {    if (this.disableMBeanRegistry) {Registry.disableRegistry();    }    // 構(gòu)建tomcat對(duì)象    Tomcat tomcat = new Tomcat();    // 設(shè)置相關(guān)的屬性    File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");    tomcat.setBaseDir(baseDir.getAbsolutePath());    for (LifecycleListener listener : this.serverLifecycleListeners) {tomcat.getServer().addLifecycleListener(listener);    }    Connector connector = new Connector(this.protocol);    connector.setThrowOnFailure(true);    tomcat.getService().addConnector(connector);    customizeConnector(connector);    tomcat.setConnector(connector);    tomcat.getHost().setAutoDeploy(false);    configureEngine(tomcat.getEngine());    for (Connector additionalConnector : this.additionalTomcatConnectors) {tomcat.getService().addConnector(additionalConnector);    }    prepareContext(tomcat.getHost(), initializers);    // 啟動(dòng)tomcat,這個(gè)方法內(nèi)部有this.tomcat.start();    return getTomcatWebServer(tomcat);}

spring boot啟動(dòng)的時(shí)候啟動(dòng)tomcat

  • SpringBoot的啟動(dòng)過(guò)程中,會(huì)調(diào)用核心的refresh方法,內(nèi)部會(huì)執(zhí)行onRefresh()方法,onRefresh()方法是一個(gè)模板方法,他會(huì)執(zhí)行會(huì)執(zhí)行子類(lèi)ServletWebServerApplicationContext的onRefresh()方法。
protected void onRefresh() {    // 模板方法,先調(diào)用它父類(lèi)的,一般是空方法    super.onRefresh();    try {// 創(chuàng)建web容器createWebServer();    }    catch (Throwable ex) {throw new ApplicationContextException("Unable to start web server", ex);    }}

這個(gè)方法會(huì)調(diào)用createWebServer()方法。

// 最核心的倆行代碼private void createWebServer() {    ......    // 獲取web容器,多個(gè)或者沒(méi)有的時(shí)候報(bào)錯(cuò)    ServletWebServerFactory factory = getWebServerFactory();    // 調(diào)用這個(gè)容器的getWebServer方法,上面的啟動(dòng)tomcat的方法!    this.webServer = factory.getWebServer(getSelfInitializer());    ......}
  • getWebServerFactory控制項(xiàng)目組有且只能有一個(gè)web容器!
protected ServletWebServerFactory getWebServerFactory() {    // Use bean names so that we don"t consider the hierarchy    // 得到所有類(lèi)型為ServletWebServerFactory的Bean。TomcatServletWebServerFactory、JettyServletWebServerFactory、UndertowServletWebServerFactory都是他得到子類(lèi)!    String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);    // 不存在,報(bào)錯(cuò)    if (beanNames.length == 0) {throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.");    }    // 存在不止一個(gè),報(bào)錯(cuò)!    if (beanNames.length > 1) {throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));    }    // 返回唯一的一個(gè)web容器!    return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);}

獲取tomcat的配置

  • 自動(dòng)配置類(lèi)ServletWebServerFactoryAutoConfiguration上除了import三個(gè)web容器,還import了BeanPostProcessorsRegistrar。
  • BeanPostProcessorsRegistrar實(shí)現(xiàn)了ImportBeanDefinitionRegistrar,所以他會(huì)在spring啟動(dòng)的時(shí)候調(diào)用registerBeanDefinitions方法。
  • registerBeanDefinitions會(huì)注冊(cè)一個(gè)Bean:webServerFactoryCustomizerBeanPostProcessor。
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {    // Bean工廠,一個(gè)Aware回調(diào)進(jìn)行賦值    if (this.beanFactory == null) {return;    }    // 注冊(cè)webServerFactoryCustomizerBeanPostProcessor這個(gè)Bean。    registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",WebServerFactoryCustomizerBeanPostProcessor.class,WebServerFactoryCustomizerBeanPostProcessor::new);    // 注冊(cè)errorPageRegistrarBeanPostProcessor    registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor",ErrorPageRegistrarBeanPostProcessor.class, ErrorPageRegistrarBeanPostProcessor::new);}
  • webServerFactoryCustomizerBeanPostProcessor實(shí)現(xiàn)了BeanPostProcessor,所以他會(huì)在啟動(dòng)的時(shí)候調(diào)用postProcessBeforeInitialization方法。
private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {    // 找到WebServerFactoryCustomizer的Bean    LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)// 標(biāo)記日志用的類(lèi).withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)// 調(diào)用customize方法,傳入webServerFactory.invoke((customizer) -> customizer.customize(webServerFactory));}
  • postProcessBeforeInitialization中會(huì)調(diào)用WebServerFactoryCustomizer類(lèi)customize方法,在系統(tǒng)中的唯一實(shí)現(xiàn):ServletWebServerFactoryCustomizer的customize方法。
  • customize把配置中的內(nèi)容設(shè)置到ConfigurableServletWebServerFactory對(duì)象中。他的實(shí)現(xiàn)TomcatServletWebServerFactory在啟動(dòng)的時(shí)候就會(huì)有值!
@Overridepublic void customize(ConfigurableServletWebServerFactory factory) {    PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();    map.from(this.serverProperties::getPort).to(factory::setPort);    map.from(this.serverProperties::getAddress).to(factory::setAddress);    map.from(this.serverProperties.getServlet()::getContextPath).to(factory::setContextPath);    map.from(this.serverProperties.getServlet()::getApplicationDisplayName).to(factory::setDisplayName);    map.from(this.serverProperties.getServlet()::isRegisterDefaultServlet).to(factory::setRegisterDefaultServlet);    map.from(this.serverProperties.getServlet()::getSession).to(factory::setSession);    map.from(this.serverProperties::getSsl).to(factory::setSsl);    map.from(this.serverProperties.getServlet()::getJsp).to(factory::setJsp);    map.from(this.serverProperties::getCompression).to(factory::setCompression);    map.from(this.serverProperties::getHttp2).to(factory::setHttp2);    map.from(this.serverProperties::getServerHeader).to(factory::setServerHeader);    map.from(this.serverProperties.getServlet()::getContextParameters).to(factory::setInitParameters);    map.from(this.serverProperties.getShutdown()).to(factory::setShutdown);    for (WebListenerRegistrar registrar : this.webListenerRegistrars) {registrar.register(factory);    }    if (!CollectionUtils.isEmpty(this.cookieSameSiteSuppliers)) {factory.setCookieSameSiteSuppliers(this.cookieSameSiteSuppliers);    }}

ServletWebServerFactoryCustomizer這個(gè)Bean是哪里的?

  • 在我們自動(dòng)配置類(lèi)ServletWebServerFactoryAutoConfiguration中定義。
@Beanpublic ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties, ObjectProvider<WebListenerRegistrar> webListenerRegistrars, ObjectProvider<CookieSameSiteSupplier> cookieSameSiteSuppliers) {    return new ServletWebServerFactoryCustomizer(serverProperties,webListenerRegistrars.orderedStream().collect(Collectors.toList()),cookieSameSiteSuppliers.orderedStream().collect(Collectors.toList()));}

到此這篇關(guān)于Spring boot整合tomcat底層原理的文章就介紹到這了,更多相關(guān)Spring boot整合tomcat內(nèi)容請(qǐng)搜索以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持!

標(biāo)簽: Tomcat
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲精品午夜av福利久久蜜桃| 国产亚洲高清在线观看| 日本午夜精品久久久久| 91午夜精品| 美女毛片一区二区三区四区最新中文字幕亚洲 | 欧美在线亚洲| 国产精品外国| 国产精品视频首页| 水蜜桃精品av一区二区| 国产美女高潮在线| 欧美日韩国产高清| 日韩午夜视频在线| 精品99在线| 爽好多水快深点欧美视频| 91免费精品国偷自产在线在线| 国产中文字幕一区二区三区| 99国产精品免费视频观看| 亚洲字幕久久| 国产一区2区在线观看| 亚洲综合二区| 免费在线日韩av| 欧美日韩高清| 欧美精品国产白浆久久久久| 久久九九99| 日韩精品亚洲专区在线观看| 欧美天堂视频| 91成人在线精品视频| 欧美日韩国产一区二区三区不卡 | 99久久亚洲精品| 日本不卡视频一二三区| 亚洲高清不卡| 精品国产三区在线| 中文字幕亚洲影视| 久久影视一区| 超级白嫩亚洲国产第一| 久久国产三级| 免费久久99精品国产| 成人亚洲欧美| 国产精品啊啊啊| 日韩黄色在线观看| 久久国产精品99国产| 久久国产电影| 秋霞国产精品| 日韩高清中文字幕一区二区| 国产精品.xx视频.xxtv| 日本亚州欧洲精品不卡| 每日更新成人在线视频| 国产91精品对白在线播放| 日韩欧美中文| 91精品国产乱码久久久久久久| 色一区二区三区四区| 国产精品成久久久久| 国产精品大片| 九九久久国产| 精品国产aⅴ| 久久男人av| 精品久久亚洲| 激情亚洲影院在线观看| 国产91在线播放精品| 成人国产精品一区二区免费麻豆| 日韩va欧美va亚洲va久久| 欧美在线不卡| 久久精品亚洲一区二区| 最近高清中文在线字幕在线观看1| 成人亚洲精品| 亚洲国产不卡| 日本亚州欧洲精品不卡| 日韩精品乱码av一区二区| 91午夜精品| 97精品国产福利一区二区三区| 91精品国产调教在线观看| 蜜臀a∨国产成人精品| 国产情侣久久| 麻豆精品蜜桃| 蜜乳av另类精品一区二区| 国产亚洲精品精品国产亚洲综合| 麻豆中文一区二区| 成人高清一区| 欧美精品一卡| 国产亚洲精品精品国产亚洲综合| 欧美激情综合| 黄色亚洲在线| 欧美交a欧美精品喷水| 精品91福利视频| 麻豆亚洲精品| 精品日韩在线| 婷婷综合社区| 久久影院资源站| 蜜桃视频欧美| 国产日产精品_国产精品毛片| 国产精品久久久久蜜臀| 国产精品社区| 国产激情在线播放| 亚洲三级在线| 日韩国产欧美| 亚洲3区在线| 91精品国产调教在线观看| 四虎成人精品一区二区免费网站| 国产伦精品一区二区三区视频| 婷婷亚洲五月色综合| 精品久久亚洲| 欧美一区久久| 久久亚洲国产精品一区二区| 国产黄大片在线观看| 日韩区一区二| 99国产精品视频免费观看一公开| 国产一区二区三区四区二区| 91精品成人| 日韩中文影院| 国产成人精品亚洲线观看| 亚州av日韩av| 免费国产自线拍一欧美视频| 亚洲国产福利| 在线精品一区| 老司机久久99久久精品播放免费| 久久久久国产一区二区| 国产精品久久久久久久久久白浆| 午夜在线观看免费一区| 亚洲一本视频| 亚洲永久字幕| 黑丝一区二区三区| 久久中文字幕av| 午夜国产一区二区| 黄色成人91| 亚洲一区av| 亚洲免费一区三区| 亚洲另类av| 色综合视频一区二区三区日韩| 久久国产亚洲| 婷婷综合网站| 久久亚洲风情| 日韩精品亚洲专区| 少妇高潮一区二区三区99| 在线精品亚洲| 91福利精品在线观看| 久久99久久人婷婷精品综合| 国产精品久久久久久模特 | 久久亚洲国产精品一区二区| 婷婷亚洲五月色综合| 久久久久亚洲| 亚洲国产一区二区在线观看 | 亚洲欧美日韩国产一区二区| 一区二区国产在线| 欧美日韩精品一区二区三区视频 | 国产精品流白浆在线观看| 国产一区二区三区久久| 九九精品调教| 亚洲一区av| 精品视频在线一区二区在线| 久久青草久久| 日本不卡高清视频| 日韩av专区| 免费精品视频在线| 精品国产91| 欧美综合二区| 国内揄拍国内精品久久| 激情自拍一区| 欧美精品国产| 欧美13videosex性极品| 美女网站久久| 日韩精品1区| 日本aⅴ免费视频一区二区三区| sm捆绑调教国产免费网站在线观看| 在线国产一区二区| 麻豆国产欧美日韩综合精品二区| 午夜国产精品视频免费体验区| 国产日产一区| 午夜一级久久| 播放一区二区| 国产欧美亚洲精品a| 一区二区自拍| 伊人久久高清| 精品久久在线| 日韩一区二区三区精品 | 国产欧美日韩精品高清二区综合区 | 精品91久久久久| 国产精品白浆| 亚洲影院天堂中文av色| 免费视频一区三区| 视频在线不卡免费观看| 国产欧美一区| 日本aⅴ亚洲精品中文乱码| 一级欧洲+日本+国产| 欧美精品日日操| av中文字幕在线观看第一页| 欧美精品不卡| 久久av网站| 捆绑调教美女网站视频一区| 国产亚洲电影| 国产伦乱精品| 欧美日本不卡| 免费在线观看一区二区三区| 欧美日韩尤物久久| 精品亚洲美女网站| 亚洲天堂一区二区| 亚洲黄色免费av| 香蕉久久国产| 国产视频一区三区| 一区在线观看| 亚洲网址在线观看|