您好,登錄后才能下訂單哦!
本篇內容介紹了“springboot中SpringApplication的run方法”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
public ConfigurableApplicationContext run(String... args) { // 構造一個任務執行觀察器(Java 查看時間和性能的類) StopWatch stopWatch = new StopWatch(); // 開始執行,記錄開始時間 stopWatch.start(); // 定制配置上下文,頂級父類包含Bean Factory ConfigurableApplicationContext context = null; // 定義一個錯誤集合(用來支持報告關于啟動的錯) Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); //定義一個 awt 的headless(設置headless模式,名字為 java.awt.headless 的系統屬性設置為true) configureHeadlessProperty(); // 獲取一個run監聽器,主要監聽SpringApplication對象,(內部只有一個EventPublishingRunListener) SpringApplicationRunListeners listeners = getRunListeners(args); //調用監聽器的啟動,當SpringApplication對象的run方法剛啟動的時候(依靠SimpleApplicationEventMulticaster) listeners.starting(); try { // 構造一個應用程序參數持有類 應用參數化 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); //創建并配置Environment(該過程會獲取入參、加載application配置文件),配置環境(Environment)加入到監聽器對象中(SpringApplicationRunListeners) ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); // 配置bean的忽略信息 掃描 pring.beaninfo.ignore 進行屬性讀取 可選true/false (在application文件中配置) configureIgnoreBeanInfo(environment); //打印logo 即pringboot的beaninfo.ignore樣圖 Banner printedBanner = printBanner(environment); // 根據應用類型創建對應的Context容器 初始化bean *** context = createApplicationContext(); // 從配置文件中獲取具體是實現類 exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); // 刷新Context之前的準備 即準備使用上下文 // 將SpringApplicationRunListeners、ConfigurableEnvironment、ApplicationArguments、Banner等重要組件雨上下文對象關聯 prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 刷新Context容器 *** // 實現spring-boot-starter-*(mybatis、redis等)自動化配置的關鍵,包括spring.factories的加載,bean的實例化等核心工作 refreshContext(context); // 刷新Context容器之后處理 afterRefresh(context, applicationArguments); // 執行結束,記錄執行時間 stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } // Context容器刷新完畢發布,這里接受ApplicationStartedEvent事件的listener會執行相應的操作 //【Spring容器已經刷新過且應用已經啟動,但是CommandLineRunners和ApplicationRunners還未調用,直接通過spring容器自己發送 // (因為ApplicationListener已經加入spring容器)】 listeners.started(context); // 觸發Context容器refresh完以后的執行 喚醒運行線程 callRunners(context, applicationArguments); } catch (Throwable ex) { // 啟動錯誤報告處理 handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { // Context啟動完畢,Runner運行完逼發布,這里接受ApplicationStartedEvent事件的listener會執行相應的操作 //【已經調用了CommandLineRunners,直接通過spring容器自己發送(因為ApplicationListener已經加入spring容器)】 listeners.running(context); } catch (Throwable ex) { // 啟動錯誤報告處理 handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } // 返回Spring容器 return context; }
返回的對象 ConfigurableApplicationContext 就是 applicationContext 子類,前者相比后者提供了更多的功能,比如實現 Lifecycle, Closeable 接口 更好的管理bean的聲明周期,還有其他的 諸如:addBeanFactoryPostProcessor,setParent,setId,addApplicationListener,addProtocolResolver 等額外的功能。
創建并啟動觀察器
設置 java.awt.headless 系統變量
加載所有 classpath 下的 META-INF/spring.factories 中的 SpringApplicationRunListener
依次調用的 SpringApplicationRunListener 的 starting 方法,發布 springboot 啟動事件
實例化 ApplicationArguments 對象 獲取應用參數
創建 ConfigurableEnvironment 對象 environment
注意 webApplicationType 控制創建的 Environment 對象的類型,當為 SERVLET 時為 StandardServletEnvironment.class,當為 REACTIVE 時為 StandardReactiveWebEnvironment.class,其余為 StandardEnvironment.class
配置 environment 對象,主要把方法參數配置到 environment 中--通過 configurePropertySources(environment, args) 設置 properties ,通過 configureProfiles(environment, args) 設置 profiles
執行所有 SpringApplicationRunListeners 的 environmentPrepared 方法發布 environmentPrepared 事件,即調用 實現ApplicationListener接口 ConfigFileApplicationListener 的 onApplicationEvent 事件
注意 該事件獲取 EnvironmentPostProcessor類型的工廠類實例集合,并將ConfigFileApplicationListener實例追加入該集合,遍歷該實例集合 一次執行postProcessEnvironment方法 分別設置 environment的propertySource屬性中的systemEnvironment屬性、propertySourceList屬性、加載YML配置文件
即把當前的 environment 和當前的 springApplication 綁定
將 ConfigurationPropertySource 放入 environment 的 propertysource 中的第一個
打印 Banner
創建Spring容器
從配置文件中獲取具體異常實現類
設置spring容器的 environment
當 beanNameGenerator 屬性存在,向bean工廠中注冊 beanNameGenerator; 當resourceLoader屬性存在,如果 context 實現GenericApplicationContext 則把其賦值給上下文中的 resourceLoader 屬性,如果 context 實現DefaultResourceLoader 則獲取其加載器,賦值給上下文中的 classLoader 屬性
回調 ApplicationContextInitializer 的 initialize 方法來初始化 context,其中還檢測各個 ApplicationContextInitializer 是否接受該類型的容器
注意 其在 context 中注冊兩個監聽器‘ConditionEvaluationReportListener’和‘ServerPortInfoApplicationContextInitializer’,同時也在 context 中注冊兩個bean工廠后置處理器‘CachingMetadataReaderFactoryPostProcessor’和‘ConfigurationWarningsPostProcessor’
執行所有 SpringApplicationRunListener 的 contextPrepared 方法,但目前是個空實現
context 中分別注冊 springApplicationArguments 和 springBootBanner 這兩個單例bean
獲取我們的 primarySources 和 sources 加載注冊到context中的 beanFactory里,即注冊主類到beanFactory
執行所有 SpringApplicationRunListener 的 contextLoaded 方法,首先判斷 ApplicationListener 是否屬于 ApplicationContextAware,如果是的話就將spring容器賦值給該 listener,然后將該 ApplicationListener 賦值給spring容器,然后調用 ApplicationListener 的 onApplicationEvent 方法
注意 該處向context注冊了10個監聽器(listeners屬性的值)和一個bean工廠后置處理器‘PropertySourceOrderingPostProcessor’,并注冊了一個單例bean(SpringBootloggingSystem)
調用 AbstractApplicationContext 的 refresh 方法刷新Spring容器
設置些初始的操作(開啟激活,啟動日期,初始化propertySource)、配置工廠的標準上下文特征、注冊 BeanPostProcessor 和 BeanFactoryPostProcessor(前者實現對bean初始化前后進行設置,后實現對 beanFactory 進行修改 或對 beanDefinition 進行修改或者增加或者初始化渴望提前初始化的 bean)、初始化國際化文件、初始化web容器、實例化非懶加載的剩余 bean 等等操作
調用 AbstractApplicationContext 的 registerShutdownHook 方法,注冊一個線程該線程主要指向 doclose 方法
執行所有 SpringApplicationRunListener 的 started 方法,發布 started 事件
回調 callrunners 方法從spring容器中獲取 ApplicationRunner 和 CommandLineRunner 對象,然后按照順序排序,循環調用他們的 run 方法
執行所有 SpringApplicationRunListener 的 running 方法,發布 running 事件
第五步到二十五步執行過程中出現異常調用 handleRunFailure 方法處理不同的異常狀態異常,調用 listeners.failed(context, exception),并關閉spring容器
“springboot中SpringApplication的run方法”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。