最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

分析SpringBoot的啟動原理

 更新時間:2020年09月14日 10:04:33   作者:編程一生  
這篇文章主要分析了SpringBoot的啟動原理,幫助大家更好的理解和使用spring boot框架,感興趣的朋友可以了解下

背景

1> 大家都知道SpringBoot是通過main函數(shù)啟動的,這里面跟蹤代碼到處都沒有找到while(true),為什么啟動后可以一直跑?

2> SpringBoot默認(rèn)使用tomcat作為web容器。大家也可以通過在pom文件中exclusion掉tomcat,denpendency jetty 的方法來使用jetty。那SpringBoot是怎么做到在不同web容器之間切換的呢?

3> 傳統(tǒng)的web容器比如jetty本質(zhì)上是直接通過java start.jar 來啟動,之后來加載spring上下文的,SpringBoot通過main函數(shù)是怎么來啟動web容器的呢?

本文就這三個問題展開論述。

問題1分析

問題1很簡單,啟動后一直跑是因為啟動了線程池。原理就是有非deamon的線程在跑。Java虛擬機(jī)規(guī)范定義要等所有用戶線程都運(yùn)行完才會退出。

所以這個原理就和下面啟動線程池一樣

程序員修煉之道教我們:不要假定,要證明。雖然jetty使用線程池是常識,我們也來跟蹤下源碼,看看線程池是在哪里初始化的:

org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory類里,創(chuàng)建Server的使用使用線程池作為初始化參數(shù)。然后創(chuàng)建了socket連接來監(jiān)聽端口。(對于socket連接有之前沒接觸過的,可以自己查一下。建議動手實踐?!禞ava異常處理總結(jié)》這篇文章里有不錯的簡單小例子可以實操下。)

到這里,大家應(yīng)該都明白了為什么啟動后一直不停。但是又有疑問了:JettyServletWebServerFactory是個什么東東?

問題2分析

關(guān)于問題2,我們寫個最簡單的類來debug一下:

進(jìn)入SpringAppication.run的源碼可以看到,里面創(chuàng)建了一個context,默認(rèn)是AnnotationConfigServletWebServerApplicationContext。一初始化,在Bean定義里就加載了spring開天辟地的5個Bean。

繼續(xù)向下執(zhí)行走到AbstractApplicationContext的refresh方法,執(zhí)行到onRefresh時,你進(jìn)入方法里發(fā)現(xiàn)實際上執(zhí)行的是

ServletWebServerApplicationContext的onFresh

這里面實際只做了一件事:創(chuàng)建web服務(wù)。

進(jìn)入這個方法,debug到getWebServerFactory

來看一下:

獲取的正式JettyServletWebServerFactory。為啥不是TomcatServlet呢?ServletWebServerFactoryAutoConfiguration的源碼很好的說明了這個問題。源碼的大意是當(dāng)tomcat依賴存在就用tomcat,不然就按順序找jetty存不存在,不存在再找Undertow存不存在。找到了就返回這個bean作為Servlet的工廠類。

@Configuration
@AutoConfigureOrder(-2147483648)
@ConditionalOnClass({ServletRequest.class})
@ConditionalOnWebApplication(
  type = Type.SERVLET
)
@EnableConfigurationProperties({ServerProperties.class})
@Import({ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, EmbeddedTomcat.class, EmbeddedJetty.class, EmbeddedUndertow.class})
public class ServletWebServerFactoryAutoConfiguration {
  public ServletWebServerFactoryAutoConfiguration() {
  }

  @Bean
  public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
    return new ServletWebServerFactoryCustomizer(serverProperties);
  }

  @Bean
  @ConditionalOnClass(
    name = {"org.apache.catalina.startup.Tomcat"}
  )
  public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) {
    return new TomcatServletWebServerFactoryCustomizer(serverProperties);
  }

  public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
    private ConfigurableListableBeanFactory beanFactory;
    public BeanPostProcessorsRegistrar() {
    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
      if (beanFactory instanceof ConfigurableListableBeanFactory) {
        this.beanFactory = (ConfigurableListableBeanFactory)beanFactory;
      }

    }

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
      if (this.beanFactory != null) {
        this.registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor", WebServerFactoryCustomizerBeanPostProcessor.class);
        this.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);
      }

    }
  }
}

至此第二個問題也真相大白。

問題3分析

第三個問題是傳統(tǒng)的web容器比如jetty本質(zhì)上是直接通過java start.jar 來啟動,之后來加載spring上下文的,SpringBoot通過main函數(shù)是怎么來啟動web容器。

這個問題在前面問題分析過程中也給了很多線索。我們來回顧下:SpringApplication.run里會創(chuàng)建Spring的應(yīng)用上下文,默認(rèn)是AnnotationConfigServletWebServerApplicationContext。首先會加載Spring開天辟地的5個Bean。然后它初始化各種Bean工廠。

SpringBoot在ServletWebServerApplicationContext中重載了onRefresh方法,除了以前Spring默認(rèn)的onRefresh方法外還增加了createWebServer方法,在這個方法中對Web容器進(jìn)行了初始化工作。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <version>${spring.boot.version}</version>
  <exclusions>
    <exclusion>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-logging</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
    </exclusion>
    <exclusion>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-jetty</artifactId>
  <version>${spring.boot.version}</version>
  <exclusions>
    <exclusion>
      <groupId>org.eclipse.jetty.aggregate</groupId>
      <artifactId>jetty-all</artifactId>
    </exclusion>
  </exclusions>
</dependency>

因為選擇servlet容器是類似于使用基于條件的注解方式。因為當(dāng)exclusion掉tomcat后,只有jetty滿足條件,所以會加載JettyServletWebServerFactory。

通過getWebServer方法會new一個WebServer對象,new對象的方法會調(diào)用initialize方法,在這個方法中會對容器進(jìn)行初始化并啟動。

而容器啟動的基本原理就是創(chuàng)建個線程池和網(wǎng)絡(luò)套接字。用線程去處理套接字讀寫的內(nèi)容。

總結(jié)

文本用帶有少許說明的三個問題開場展開論述,實際是使用了麥肯錫大法中的SCQA架構(gòu)。

SCQA架構(gòu)是金字塔模型里面突出的一個論述方法,即“情境(Situation)、沖突(Complication)、問題(Question)、答案(Answer)”??梢詭椭覀冊陉愂鍪聦崟r條理更為清晰、有效。

SCQA其實只是麥肯錫做了總結(jié)。這個方法李清照都在用:

昨夜雨疏風(fēng)驟,濃睡不消殘酒 (情境)

試問卷簾人,渠道海棠依舊(沖突)

知否,知否(問題)

應(yīng)是綠肥紅瘦(答案)

文章正文看似一步步回答問題,實際上在講述怎樣去看spring源碼,了解spring原理的一個過程。即:帶著問題去看,debug跟蹤源碼驗證 的方法。

以上就是分析SpringBoot的啟動原理的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot 啟動原理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 關(guān)于@Valid注解大全以及用法規(guī)范

    關(guān)于@Valid注解大全以及用法規(guī)范

    這篇文章主要介紹了關(guān)于@Valid注解大全以及用法規(guī)范,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • SpringBoot 在項目啟動之后執(zhí)行自定義方法的兩種方式小結(jié)

    SpringBoot 在項目啟動之后執(zhí)行自定義方法的兩種方式小結(jié)

    這篇文章主要介紹了SpringBoot 在項目啟動之后執(zhí)行自定義方法的兩種方式小結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • springcloud部署提示 找不到url的解決

    springcloud部署提示 找不到url的解決

    這篇文章主要介紹了springcloud部署提示 找不到url的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。
    2022-01-01
  • springboot中的springSession的存儲和獲取實現(xiàn)

    springboot中的springSession的存儲和獲取實現(xiàn)

    這篇文章主要介紹了springboot中的springSession的存儲和獲取實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 詳解java中if語句和switch的使用

    詳解java中if語句和switch的使用

    這篇文章主要介紹了java中if語句和switch的使用,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • 使用Guava?Cache原理及最佳實踐

    使用Guava?Cache原理及最佳實踐

    文章介紹了GuavaCache,這是一種支持高并發(fā)的本地緩存,它支持多種回收策略,如基于容量、時間和引用的回收,并提供了自動加載、定時刷新和顯式清除緩存的功能,文章還討論了GuavaCache的適用場景和使用方法,并通過代碼示例和源碼分析,幫助讀者更好地理解和使用GuavaCache
    2025-02-02
  • Java實現(xiàn)俄羅斯方塊小游戲源碼

    Java實現(xiàn)俄羅斯方塊小游戲源碼

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)俄羅斯方塊小游戲源碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Spring MVC 學(xué)習(xí) 之 - URL參數(shù)傳遞詳解

    Spring MVC 學(xué)習(xí) 之 - URL參數(shù)傳遞詳解

    本篇文章主要介紹了SpringMVC-URL參數(shù)傳遞,在學(xué)習(xí) Spring Mvc 過程中,有必要來先了解幾個關(guān)鍵參數(shù),有興趣的可以了解一下。
    2017-01-01
  • Springboot自動裝配之注入DispatcherServlet的實現(xiàn)方法

    Springboot自動裝配之注入DispatcherServlet的實現(xiàn)方法

    這篇文章主要介紹了Springboot自動裝配之注入DispatcherServlet,Springboot向外界提供web服務(wù),底層依賴了springframework中的web模塊來實現(xiàn),那么springboot在什么時機(jī)向容器注入DispatcherServlet這個核心類的呢?帶著這個問題一起通過本文學(xué)習(xí)吧
    2022-05-05
  • spring接口通過配置支持返回多種格式(xml,json,html,excel)

    spring接口通過配置支持返回多種格式(xml,json,html,excel)

    這篇文章主要給大家介紹了關(guān)于spring接口如何通過配置支持返回多種格式(xml,json,html,excel)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-12-12

最新評論

赞皇县| 景德镇市| 诏安县| 清丰县| 翁牛特旗| 白水县| 兴义市| 平凉市| 阜新市| 门头沟区| 祥云县| 安平县| 安徽省| 福清市| 永新县| 中江县| 宣化县| 台江县| 平原县| 南昌市| 福清市| 定南县| 安平县| 门头沟区| 镇雄县| 施甸县| 东光县| 建始县| 扎赉特旗| 遂溪县| 和政县| 石林| 三都| 赤峰市| 万源市| 阿坝县| 嘉禾县| 青神县| 治县。| 富平县| 怀远县|