
構造方法初始化,創建一個新的實例,這個應用程序的上下文要從指定的來源加載bean public SpringApplication(ResourceLoaderresourceLoader,Class<?>...primarySources){ this.sources=newLinkedHashSet(); this.bannerMode=Mode.CONSOLE; this.logStartupInfo=true; this.addCommandLineProperties=true; this.headless=true; this.registerShutdownHook=true; this.additionalProfiles=newHashSet(); 初始化資源加載器,默認為null this.resourceLoader=resourceLoader; 斷言要加載的資源類不能為null否則報錯 Assert.notNull(primarySources,"Primary Sources must not be null"); 初始化主要加載資源並去重 this.primarySources=newLinkedHashSet(Arrays.asList(primarySources)); 判斷當前應用程序的類型 NONE/SERVLET/REACTIVE this.webApplicationType=this.deduceWebApplicationType(); 加載所有的初始化容器,設置應用上下文初始化器,從"META-INF/spring.factories"讀取ApplicationContextInitializer類的實例名稱集合並去重,並進行set去重。(一共5個) this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class)); 設置監聽器,從"META-INF/spring.factories"讀取ApplicationListener類的實例名稱集合並去重,並進行set去重。(一共10個) this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); 推斷主入口應用類,通過當前調用棧,獲取Main方法所在類,並賦值給mainApplicationClass this.mainApplicationClass=this.deduceMainApplicationClass(); } 啟動流程 springboot啟動的運行方法,可以看到主要是各種運行環境的准備工作 public ConfigurableApplicationContext run(String...args){ 創建並啟動計時監控類 設置當前任務的id和啟動的時間,方便后續的時候進行計時的操作 StopWatch stopWatch=new StopWatch(); stopWatch.start(); 初始化上下文 初始化異常報告集合 ConfigurableApplicationContext context=null; Collection<SpringBootExceptionReporter> exceptionReporters=new ArrayList(); 設置系統屬性“java.awt.headless” 默認為true,用於運行headless服務器,進行簡單的圖像處理,多用於在缺少顯示屏、鍵盤或者鼠標時的系統配置,很多監控工具如jconsole 需要將該值設置為true this.configureHeadlessProperty(); 注冊linsteners,創建所有spring運行監聽器並發布應用啟動事件,簡單說的話就是獲取SpringApplicationRunListener類型的實例(EventPublishingRunListener對象),並封裝進SpringApplicationRunListeners對象,然后返回這個SpringApplicationRunListeners對象。說的再簡單點,getRunListeners就是准備好了運行時監聽器EventPublishingRunListener。 記載spring.factoris文件中的你內容 獲取文件中對應類的全路徑 根據反射得到具體的實體類對象 生成對應的對象之后再返回給調用者 SpringApplicationRunListeners listeners=this.getRunListeners(args); 每次監聽器在實際做操作的時候都會執行listeners.starting() this.initialMulticaster.multicastEvent 匹配不同類型的事件,然后從所有的監聽器中把不符合條件的監聽給過濾掉 符合條件的監聽器會循環執行具體的自己的處理邏輯 listeners.starting(); try{ 初始化默認參數應用類 加載命令行的參數值,解析在命令行中通過--key=value輸入的屬性值,封裝到ApplicationArguments對象中 ApplicationArguments applicationArguments=new DefaultApplicationArguments(args); 根據運行監聽器和應用參數來准備spring環境 ConfigurableEnvironment environment=this.prepareEnvironment(listeners,applicationArguments); 設置系統屬性,保證某些bean不會添加到准備的環境中(設置忽略的參數) this.configureIgnoreBeanInfo(environment); 創建banner打印類 Banner printedBanner=this.printBanner(environment); 創建應用上下文對象,根據當前應用類型選擇創建什么類型的上下文 servlet,reactive,none context=this.createApplicationContext(); 設置異常報告對象,用來支持報告關於啟動的錯誤 this.getSpringFactoriesInstances(SpringBootExceptionReporter.class,newClass[]{ConfigurableApplicationContext.class},context); 准備當前上下文對象,包含一個關鍵操作,將啟動類注入容器,為后續開啟自動化提供基礎 設置初始化進行執行,向beanfactory中注入了三個postprocessor的對象,后續在自動裝配的時候會用到applyInitializers(context); listeners.contextPrepared(context); 加載很多資源配置,自動裝配在此環節完成load(context, sources.toArray(new Object[0])); listeners.contextLoaded(context); this.prepareContext(context,environment,listeners,applicationArguments,printedBanner); 刷新應用上下文 this.refreshContext(context); 應用上下文刷新后置操作做一些擴展功能 this.afterRefresh(context,applicationArguments); 計時結束,並打印程序所用時長 stopWatch.stop(); 輸出日志,記錄執行的主類目和事件信息 if(this.logStartupInfo){ (newStartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(),stopWatch); } 啟動所有的監聽器對象 listeners.started(context); 執行所有的runner運行器 this.callRunners(context,applicationArguments); }catch(Throwablevar9){ 處理失敗的操作 this.handleRunFailure(context,listeners,exceptionReporters,var9); thrownewIllegalStateException(var9); } 啟動完成調用,發布應用上下文就緒事件 listeners.running(context); 返回應用上下文 return context; }