Spring boot-(3) Spring Boot特性1
本節將深入Spring Boot的細節,可以學到你想使用的或定制的Spring Boot的主要特性。
1. SpringApplication
SpringApplication類為引導一個Spring應用提供了方便的方法,該Spring應用從main方法開啟。通常,你可以通過靜態方法SpringApplication.run方法,如下所示:
public static void main(String[] args) { SpringApplication.run(MySpringConfiguration.class, args); }View Code
當應用啟動時,你可以看到如下類似的輸出,默認情況下,INFO級別的日誌信息將會展示,包含相關的啟動細節,如啟動該應用的用戶等:
. ____ _ __ _ _ /\\ / ___‘_ __ _ _(_)_ __ __ _ \ \ \ ( ( )\___ | ‘_ | ‘_| | ‘_ \/ _` | \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ‘ |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: v2.0.0.BUILD-SNAPSHOT 2013-07-31 00:08:16.117 INFO 56603 --- [ main] o.s.b.s.app.SampleApplication : Starting SampleApplication v0.1.0 on mycomputer with PID 56603 (/apps/myapp.jar started by pwebb) 2013-07-31 00:08:16.166 INFO 56603 --- [ main] ationConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6e5a8246: startup date [Wed Jul 31 00:08:16 PDT 2013]; root of context hierarchy 2014-03-04 13:09:54.912 INFO 41370 --- [ main] .t.TomcatServletWebServerFactory : Server initialized with port: 8080 2014-03-04 13:09:56.501 INFO 41370 --- [ main] o.s.b.s.app.SampleApplication : Started SampleApplication in 2.992 seconds (JVM running forView Code3.658)
(1) 啟動失敗
當程序啟動失敗時,註冊的FailureAnalyzers將有機會提供具體的錯誤信息和具體的方法來修復該問題。例如,當你在8080端口開啟一個web應用,並且該端口已被使用,你可以看到如下相似信息:
*************************** APPLICATION FAILED TO START *************************** Description: Embedded servlet container failed to start. Port 8080 was already in use. Action: Identify and stop the process that‘s listening on port 8080 or configure thisView Codeapplication to listen on another port.
當任何錯誤分析器均無法處理該異常時,你仍然可以顯示全部鑒定報告,以便更好的理解哪一塊的錯誤。如果這樣做的話,需要為"org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener"啟用debug屬性或DEBUG日誌級別。例如,如果使用java -jar運行程序時,可以按如下命令啟用debug屬性:
$ java -jar myproject-0.0.1-SNAPSHOT.jar --debugView Code
(2) 自定義橫幅
啟動程序時打印的橫幅如"Spring"可以進行修改,需要通過增加banner.txt文件到classpath或者設置banner.location屬性指定該文件的位置。如果該文件非UTF-8編碼,則你需要設置banner.charset。除了文本文件,你也可以增加banner.gif, banner.jpg或banner.png圖片到classpath中,或者設置banner.image.location屬性。圖片將會被轉換為ASCII碼形式進行展現,並且展現在任何的文本橫幅之上。
在banner.txt文件中,你可以使用如下的占位符:
變量 | 含義 |
${application.version} | 應用的版本號,如MANIFEST.MF所聲明的。例如:Implemention-Version: 1.0 將會顯示1.0 |
${application.formatted-version} | 與${application.version}類似,但會被以v開頭進行格式化顯示,如:v1.0 |
${spring-boot.version} | Spring Boot的版本,如2.0.0.BUILD-SNAPSHOT。 |
${spring-boot.formatted-version} | 以v開頭格式化顯示Spring Boot的版本,如v2.0.0.BUILD-SNAPSHOT |
${Ansi.NAME}, ${AnsiColor.NAME} ${AnsiBackground.NAME}, ${AnsiStyle.NAME} |
該四個關系等價,NAME表示ANSI轉移碼的名稱 |
${application.title} | 應用的名稱,如MANIFEST.MF中所示,如:Implementation-Title: MyApp將打印MyApp |
註意:也可以通過調用SpringApplication.setBanner(Banner banner)方法設置橫幅信息,其中的banner可通過調用org.springframework.boot.Banner接口並實現printBanner()方法進行實現。
你也可使用spring.main.banner-mode屬性來決定橫幅是打印在標準輸出窗口(console), 輸出到配置的日誌log中(log),亦或是禁止生成(off)。
打印的banner將註冊為單例bean對象,並且在springBootBanner名稱之下。
(3) 自定義SpringApplication
如果默認的SpringApplication類不適合你的口味,你可以創建局部實例並定制該實例加以替代。例如,如下的關閉banner:
public static void main(String[] args) { SpringApplication app = new SpringApplication(MySpringConfiguration.class); app.setBannerMode(Banner.Mode.OFF); app.run(args); }View Code
你也可以通過application.properties文件對SpringApplication進行配置。
(4) 流暢的Builder API
如果你需要構建一個ApplicationContext層級,或者你更傾向於使用流暢的構建API,你可以使用SpringApplicationBuilder. SpringApplicationBuilder可以使你連接多個方法調用,且包含parent及child方法使你創建一個層級關系,如下所示:
new SpringApplicationBuilder() .sources(Parent.class) .child(Application.class) .bannerMode(Banner.Mode.OFF) .run(args);View Code
註意:當創建ApplicationContext層級時,有一些限制。例如,Web組件必須包含在child上下文中,相同的Environment均用於parent和child上下文中。
(5) 應用事件和監聽器
除了常用的如ContextRefreshedEvent等Spring框架的事件,一個SpringApplication也會發送一些額外的事件。
註意:一些事件實際上在ApplicationContext創建之間就被觸發,因此你不能在這些事件上註冊一個監聽器(作為@Bean)。但你可以通過調用SpringApplication.addListeners()或SpringApplicationBuilder.listeners()方法進行註冊。
如果你想自動註冊那些監聽器,而忽略應用創建的方式,你可以在項目中增加一個META-INF/spring.factories文件,並且通過使用org.springframework.context.ApplicationListener屬性引用你的監聽器,例如:
org.springframework.context.ApplicationListener = com.example.project.MyListenerView Code
當程序運行時,應用事件將會按照如下的順序進行發送:
1) 一個ApplicationStartingEvent將會在啟動時發送,但在監聽器註冊和初始化等流程之後。
2) 一個ApplicationEnvironmentPrepareEvent將會在Environment在上下文使用時發送,但在該上下文的創建之後。
3) 一個ApplicationPrepareEvent在刷新開始前發送,但在bean定義加載之後。
4) 一個ApplicationReadyEvent在刷新及任何相關回調處理之後調用,為了通知應用已經準備好服務請求。
5) 一個ApplicationFailedEvent將會被發送,如果啟動時存在異常。
註意:通常你不會使用應用事件,但知道他們的存在是有益的。本質上,Spring Boot使用事件處理很多任務。
應用事件通過Spring框架的事件發布機制進行發送。該部分機制中,確保一個事件發布到child上下文的監聽器時,也會發布到parent上下文的監聽器。這種情況產生的結果就是,如果你的應用使用SpringApplication實例的層級關系,一個監聽器可能會接收到多個同類型的應用事件的實例。
為了允許你的監聽器可以區別來自其本身上下文的事件還是來自後代上下文的事件,應該請求它的應用上下文被註入,然後比較註入的上下文和該事件的上下文。上下文的註入兩種方法實現:1) 通過實現ApplicationContextAware類;2)如果監聽器是一個bean,則使用@Autowired註解。
(6) Web環境
SpringApplication嘗試在你的立場創建ApplicationContext的正確類型。默認情況下,AnnotationConfigApplicationContext或AnnotationConfigServletWebServerApplicationContext將會被使用,取決於你是否在開發一個web應用。
決定web環境的算法相當簡單(基於當前的幾個類)。如果你想覆蓋默認情況,可以使用setWebEnvironment(boolean webEnvironment)。
也可以完全控制ApplicationContext的類型,通過調用setApplicationContextClass()方法。
註意:當在JUnit單元測試中使用SpringApplication時,通常要求調用setWebEnvironment(false)。
(7) 訪問應用參數
如果你想訪問傳入SpringApplication.run()方法中的應用參數時,你可以註入一個org.soringframework.boot.ApplicationArguments bean。該ApplicationArguments接口可以為原生的string[]參數,以及解析的option和non-option參數提供訪問。
import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.stereotype.Component; @Component public class MyBean { @Autowired public MyBean(ApplicationArguments args) { boolean debug = args.containsOption("debug"); List<String> files = args.getNonOptionArgs(); // if run with "--debug logfile.txt" debug=true, files=["logfile.txt"] } }View Code
註意:Spring Boot還向Spring環境中註冊了CommandLinePropertySource。這使得你可以通過使用@Value註解來註入單個應用程序參數。
(8) 使用ApplicationRunner或CommandLineRunner
如果你想在SpringApplication開啟時,運行一些特殊的代碼,你可以實現ApplicationRunner或CommandLineRunner接口。兩個接口工作方式相同, 均提供一個單獨的run方法,該方法在SpringApplication.run()結束時將被調用。
CommandLineRunner接口提供應用程序參數string[]的訪問,ApplicationRunner使用之前所說的ApplicationArguments接口。
import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @Component public class MyBean implements CommandLineRunner{ public void run(String... args) throws Exception { } }View Code
如果定義的多個CommandLineRunner或ApplicationRunner beans必須以指定的順序調用,可以通過如下兩種方法實現:1) 實現org.springframework.core.Ordered接口 2) 使用org.springframework.core.annotation.Order註解。
(9) 程序退出
每個SpringApplicaion為JVM註冊了一個關閉鉤子,用於確保ApplicationContext退出時可以平和地關閉。所有標準Spring生命周期的回調均可以使用,如DisposableBean接口或@PreDestory註解。
此外,當SpringApplication.exit()調用時,如果beans想要返回特殊的退出代碼,可以實現org.springframework.boot.ExitCideGenerator接口。該退出代碼然後可以傳入System.exit()來作為狀態碼返回,如下例所示:
import org.springframework.boot.ExitCodeGenerator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; @SpringBootApplication public class ExitCodeApplication { @Bean public ExitCodeGenerator exitCodeGenerator(){ return () -> 42; } public static void main(String[] args) { System.exit(SpringApplication .exit(SpringApplication.run(ExitCodeApplication.class, args))); } }View Code
此外,ExitCodeGenerator接口也可用於實現異常。當異常發生時,Spring Boot可返回基於實現getExitCode()方法提供的退出代碼。
(10) 管理特性
通過指定spring.application.admin.enabled屬性,即可使用管理相關的特性。這將在MBeanServer平臺上公開SpringApplicationAdminMXBean。你可以使用該特性來遠程管理你的Spring Boot應用。這個特性將有益於任務服務的封裝實現。
註意:
1) 如果你想知道當前程序運行於哪個HTTP端口,你可以通過local.server.port屬性得到。
2) 小心使用該特性,因為MBean公開了關閉該應用程序的方法。
Spring boot-(3) Spring Boot特性1