[TOC]
SpringApplication 是Spring Boot 提供的一個類,該類提供了一個便捷的方法引導Spring應用, 從應用的入口main() 方法啟動應用, 主方法直接調用SpringApplication.run() 方法, 類似:
```
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
```
啟動之后, 在控制臺看到如下信息代表啟動成功了。
```
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.0)
2021-11-24 07:01:30.951 INFO 1592 --- [ restartedMain] c.o.s.SpringbootEncyApplication : Starting SpringbootEncyApplication using Java 1.8.0_211 on LAPTOP-C6T2C3A5 with PID 1592 (D:\devworkspace\eclipse\springboot-ency\target\classes started by xuemi in D:\devworkspace\eclipse\springboot-ency)
2021-11-24 07:01:30.953 INFO 1592 --- [ restartedMain] c.o.s.SpringbootEncyApplication : No active profile set, falling back to default profiles: default
2021-11-24 07:01:30.992 INFO 1592 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2021-11-24 07:01:30.992 INFO 1592 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2021-11-24 07:01:31.598 INFO 1592 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2021-11-24 07:01:31.666 INFO 1592 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 60 ms. Found 2 JPA repository interfaces.
2021-11-24 07:01:32.502 INFO 1592 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-11-24 07:01:32.512 INFO 1592 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-11-24 07:01:32.512 INFO 1592 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.46]
2021-11-24 07:01:32.726 INFO 1592 --- [ restartedMain] org.apache.jasper.servlet.TldScanner : At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
2021-11-24 07:01:32.731 INFO 1592 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-11-24 07:01:32.731 INFO 1592 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1738 ms
2021-11-24 07:01:32.819 INFO 1592 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2021-11-24 07:01:33.046 INFO 1592 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2021-11-24 07:01:33.052 INFO 1592 --- [ restartedMain] o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:236bfaf5-4084-41ad-8985-f5c858eff903'
2021-11-24 07:01:33.234 INFO 1592 --- [ restartedMain] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2021-11-24 07:01:33.279 INFO 1592 --- [ restartedMain] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.4.31.Final
2021-11-24 07:01:33.401 INFO 1592 --- [ restartedMain] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2021-11-24 07:01:33.512 INFO 1592 --- [ restartedMain] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2021-11-24 07:01:34.076 INFO 1592 --- [ restartedMain] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2021-11-24 07:01:34.086 INFO 1592 --- [ restartedMain] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2021-11-24 07:01:34.150 WARN 1592 --- [ restartedMain] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-11-24 07:01:35.020 INFO 1592 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2021-11-24 07:01:35.069 INFO 1592 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2021-11-24 07:01:35.078 INFO 1592 --- [ restartedMain] c.o.s.SpringbootEncyApplication : Started SpringbootEncyApplication in 4.466 seconds (JVM running for 4.96)
```
默認情況下,控制臺會顯示 INFO 日志消息,包括一些相關的啟動詳細信息,例如啟動應用程序的用戶。 如果需要 INFO 以外的日志級別,可以進行設置,參考本系列的“4.日志”。
可以通過將 `spring.main.log-startup-info `設置為 false 來關閉啟動信息記錄。
提示: 要在啟動期間添加額外的日志記錄,您可以在 SpringApplication 的子類中覆蓋 logStartupInfo(boolean)。
## 1. 啟動失敗
如果應用啟用失敗, 注冊`FailureAnalyzers`有機會獲取更詳細的錯誤信息和解決問題的方法。比如默認的8080端口被占用,會報如下錯誤信息:
```
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-11-24 07:03:29.531 ERROR 13088 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Web server failed to start. Port 8080 was already in use.
Action:
Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.
```
注意:Spring Boot 提供了許多 FailureAnalyzer 實現,也可以添加自己的。
如果沒有錯誤分析器用來處理異常, 還是可以看到完整的報告來了解發生了什么錯誤, 只需要org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener 啟用調試屬性或啟用調試日志記錄。
比如: 如果使用java -jar 的方式運行應用程序, 則可以使用以下方式啟動調試:
`java -jar myproject-0.0.1-SNAPSHOT.jar --debug`
## 2. 懶初始化
SpringApplication支持應用程序的懶初始化。啟用懶初始化之后,Bean會在需要的時候加載, 而不是在應用啟動時加載。懶初始化的好處是可以縮短應用啟動的時間。 在Web應用中,懶初始化會讓很多Web相關的Bean 直到接受到http請求的時候才初始化。
延遲初始化的一個缺點是它會延遲發現應用程序的問題。 如果一個錯誤配置的 bean 被延遲初始化,那么在啟動過程中將不再發生故障,并且只有在 bean 初始化時問題才會被發現。 還必須注意確保 JVM 有足夠的內存來容納所有應用程序的 bean,而不僅僅是那些在啟動期間初始化的 bean。 由于這些原因,默認情況下不啟用延遲初始化,建議在啟用延遲初始化之前對 JVM 的堆大小進行微調。
懶初始化啟用的方式:
* 方式1: 配置屬性: `spring.main.lazy-initialization=true`
* 方式2: 代碼: SpringApplicationBuilder 的lazyInitialization()
* 方式3: 代碼: SpringApplication 的setLazyInitialization()
提示: 如果設置了應用的延遲初始化, 但對于某些Bean又希望不延遲, 可以使用注解 `@Lazy(false)`。
## 3. 自定義啟動的橫幅標志
Spring Boot 啟動的時候在控制臺會打印一個Spring的橫幅標志(如本篇開頭的介紹)。該橫幅標志可以自行修改, 修改的方式有:
* 在類路徑添加 banner.txt 文件
* 也可以通過spring.banner.location設置文件位置
對于 非UTF-8編碼的文件, 可以使用spring.banner.charset 設置字符集。
除了文本文件之外,也可以向類路徑添加banner.gif、banner.jpg 或banner.png 圖像文件,還可以設置spring.banner.image.location 屬性。 圖像被轉換為 ASCII 藝術表現形式并打印。
在 banner.txt 文件中,可以使用以下占位符:
| 變量 | 描述 |
| --- | --- |
| ${application.version} | 應用的版本號,在MANIFEST.MF文件中, 類似: Implementation-Version: 1.0 |
|${application.formatted-version} | 應用程序的版本號,在 MANIFEST.MF 中聲明并格式化以供顯示(用括號括起來并以 v 為前綴)。 例如 (v1.0)。 |
| ${spring-boot.version} | Spring Boot 版本, 比如 2.6.0 |
| ${spring-boot.formatted-version} | Spring Boot 版本,已格式化以顯示(用括號括起來并以 v 為前綴)。 例如 (v2.6.0) |
|`${Ansi.NAME}`(or`${AnsiColor.NAME}`,`${AnsiBackground.NAME}`,`${AnsiStyle.NAME}`) | NAME 是 ANSI 轉義碼的名稱 |
| ${application.title} | 應用程序的標題,在 MANIFEST.MF 中聲明。 例如,Implementation-Title: MyApp 打印為 MyApp。 |
提示: 以編程方式生成橫幅,則可以使用 SpringApplication.setBanner(... ) 方法。 繼承org.springframework.boot.Banner 接口并實現自己的 printBanner() 方法。
使用 spring.main.banner-mode 屬性來控制橫幅是否必須在 System.out(控制臺)上打印,或是發送到配置的記錄器(日志),或者根本不生成(關閉)
用來進行橫幅打印的單例Bean的名字是 **springBootBanner**。
注意:
${application.version} 和 ${application.formatted-version} 屬性僅在使用 Spring Boot 啟動器時可用。 如果運行一個解壓的 jar 并使用 java -cp <classpath> <mainclass> 啟動它,這些值將不會被解析。
所以建議始終使用 java org.springframework.boot.loader.JarLauncher 啟動解壓的 jar。 這將在構建類路徑和啟動應用程序之前初始化 application.* 橫幅變量。
## 4. 自定義SpringApplication
SpringApplication.run() 對應一個默認的SpringApplication實例, 也可以創建自己的SpringApplication實例并對其進行設置, 舉例來看,要關閉啟動的橫幅,可以使用如下代碼:
```
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
application.setBannerMode(Banner.Mode.OFF);
application.run(args);
}
}
```
注意:傳遞給 SpringApplication 的構造函數參數是 Spring bean 的配置源。 在大多數情況下,這些是對@Configuration 類的引用,但它們也可以是對@Component 類的直接引用。
也可以使用 application.properties 文件配置 SpringApplication。詳細可以參考 “2.配置外部化”。
## 5. 流利的構建器 API
如果需要構建 ApplicationContext 層次結構(具有父/子關系的多個上下文),或者偏好使用“流暢”的構建器 API,則可以使用 SpringApplicationBuilder。
SpringApplicationBuilder 允許將多個方法調用鏈接在一起,并包含允許創建層次結構的父方法和子方法,如下所示:
```
new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.run(args);
```
注意: 創建 ApplicationContext 層次結構時有一些限制。 例如,Web 組件必須包含在子上下文中,并且對父上下文和子上下文使用相同的環境。
## 6. 應用的可用性
在平臺上部署時,應用程序可以使用 Kubernetes Probes 等基礎設施向平臺提供有關其可用性的信息。 Spring Boot 包括對常用“活躍”和“就緒”可用性狀態的開箱即用支持。 如果使用 Spring Boot 的“actuator”支持,那么這些狀態將作為健康端點組公開。
此外,還可以通過將 ApplicationAvailability 接口注入到自己的 bean 中來獲取可用性狀態。
#### 6.1 活躍狀態(liveness)
應用程序的“活躍度”狀態表明它的內部狀態是否允許它正常工作,或者如果它當前失敗則自行恢復。 損壞的“Liveness”狀態意味著應用程序處于無法恢復的狀態,基礎設施應該重新啟動應用程序。
注意: 一般來說,“Liveness”狀態不應該基于外部檢查,例如健康檢查。 如果確實如此,則出現故障的外部系統(數據庫、Web API、外部緩存)將觸發整個平臺的大規模重啟和級聯故障。
Spring Boot 應用程序的內部狀態主要由 Spring ApplicationContext 表示。 如果應用程序上下文已成功啟動,Spring Boot 會假定應用程序處于有效狀態。 一旦上下文刷新,應用程序就被認為是活動的,可以參考 “1.7 應用事件和監聽 ” 的介紹。
#### 6.2 就緒狀態 (Readiness )
應用程序的“就緒”狀態表明應用程序是否已準備好處理流量。 失敗的“就緒”狀態告訴平臺它現在不應將流量路由到應用程序。 這通常發生在啟動期間,同時正在處理 CommandLineRunner 和 ApplicationRunner 組件,或者在應用程序確定它太忙而無法增加流量時的任何時間。
一旦應用程序和命令行運行程序被調用,應用程序就被認為已準備就緒,請參考 “1.7 應用事件和監聽 ” 的介紹
提示:預期在啟動期間運行的任務應該由 CommandLineRunner 和 ApplicationRunner 組件執行,而不是使用 Spring 組件生命周期回調,例如 @PostConstruct。
#### 6.3 管理應用程序可用性狀態
通過注入 ApplicationAvailability 接口并在其上調用方法,應用程序組件可以隨時檢索當前的可用性狀態。 更多的時候,應用程序會想要監聽狀態更新或更新應用程序的狀態。
例如,可以將應用程序的“Readiness”狀態導出到一個文件中,這樣 Kubernetes 的“exec Probe”就可以查看這個文件:
```
@Component
public class MyReadinessStateExporter {
@EventListener
public void onStateChange(AvailabilityChangeEvent<ReadinessState> event) {
switch (event.getState()) {
case ACCEPTING_TRAFFIC:
// create file /tmp/healthy
break;
case REFUSING_TRAFFIC:
// remove file /tmp/healthy
break;
}
}
}
```
還可以在應用程序中斷且無法恢復時更新應用程序的狀態:
```
@Component
public class MyLocalCacheVerifier {
private final ApplicationEventPublisher eventPublisher;
public MyLocalCacheVerifier(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void checkLocalCache() {
try {
// ...
}
catch (CacheCompletelyBrokenException ex) {
AvailabilityChangeEvent.publish(this.eventPublisher, ex, LivenessState.BROKEN);
}
}
}
```
Spring Boot 通過 Actuator Health Endpoints 為“Liveness”和“Readiness”提供 Kubernetes HTTP 探測。 可以參考: https://docs.spring.io/spring-boot/docs/current/reference/html/deployment.html#deployment.cloud.kubernetes
## 7. 應用程序事件和偵聽器
除了通常的 Spring Framework 事件(例如 ContextRefreshedEvent)之外,SpringApplication 還發送一些額外的應用程序事件。
注意:某些事件實際上是在創建 ApplicationContext 之前觸發的,因此您不能將偵聽器注冊為 @Bean。 可以使用 SpringApplication.addListeners(… ) 方法或 SpringApplicationBuilder.listeners(… ) 方法注冊它們。
應用程序運行時,應用程序事件按以下順序發送:
1.
ApplicationStartingEvent, 啟動后, 開始處理之前, 排除監聽器和初始化器的注冊
2. ApplicationEnvironmentPreparedEvent , 環境應用在上下文, 上下文創建之前
3. ApplicationContextInitializedEvent , ApplicationContext 準備好,ApplicationContextInitializers 被呼叫, Bean 的定義加載之前
4. ApplicationPreparedEvent , Bean 定義加載之后, 刷新之前
5. ApplicationStartedEvent , 刷新上下文之后但在調用任何應用程序和命令行運行程序之前。
6. AvailabilityChangeEvent 在LivenessState.CORRECT 之后, 應用啟動
7. ApplicationReadyEvent 任何應用程序和命令行運行程序被調用后執行。
8. AvailabilityChangeEvent ,ReadinessState.ACCEPTING_TRAFFIC 之后,準備好可以處理請求
9. ApplicationFailedEvent , 啟動異常
上面的列表僅包括綁定到 SpringApplication 的 SpringApplicationEvents。 除此之外,以下事件也在 ApplicationPreparedEvent 之后和 ApplicationStartedEvent 之前發布
1. WebServerInitializedEvent WebServer 準備就緒。ServletWebServerInitializedEvent 和 ReactiveWebServerInitializedEvent 分別是 servlet 和reactive
2. ContextRefreshedEvent , ApplicationContext 刷新之后
提示: 通常不需要使用應用程序事件,但知道它們存在會很方便。 在內部,Spring Boot 使用事件來處理各種任務。
注意:默認情況下,事件偵聽器不應運行在同一線程中執行的潛在冗長任務。 考慮改用應用程序和命令行運行程序。
應用程序事件是使用 Spring Framework 的事件發布機制發送的。 此機制的一部分確保發布到子上下文中的偵聽器的事件也發布到任何祖先上下文中的偵聽器。 因此,如果應用程序使用 SpringApplication 實例的層次結構,則偵聽器可能會收到同一類型應用程序事件的多個實例。
為了讓偵聽器區分其上下文的事件和后代上下文的事件,它應該請求注入其應用程序上下文,然后將注入的上下文與事件的上下文進行比較。 上下文可以通過實現 ApplicationContextAware 或者,如果監聽器是一個 bean,通過使用 @Autowired 注入。
## 8. Web 環境
SpringApplication 嘗試創建正確類型的 ApplicationContext。 如果是 Web應用,用于確定 WebApplicationType 的算法如下:
1. 如果存在 Spring MVC,則使用 AnnotationConfigServletWebServerApplicationContext
2. 如果 Spring MVC 不存在而 Spring WebFlux 存在,則使用 AnnotationConfigReactiveWebServerApplicationContext
3. 否則,使用 AnnotationConfigApplicationContext
如果同時存在Spring MVC 和Spring WebFlux, 則默認使用MVC, 可以使用 `setWebApplicationType(WebApplicationType). ` 進行設置。
也可以通過調用 setApplicationContextClass(… ) 來完全控制使用的 ApplicationContext 類型。
提示: 在 JUnit 測試中使用 SpringApplication 時,通常需要調用 setWebApplicationType(WebApplicationType.NONE)。
## 9. 訪問應用程序參數
如果需要獲取傳遞給 SpringApplication.run(... ) 的應用程序參數,可以注入一個 org.springframework.boot.ApplicationArguments 類型的bean。 ApplicationArguments 接口提供對原始 String[] 參數以及解析的選項和非選項參數的訪問,如下所示:
```
@Component
public class MyBean {
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
if (debug) {
System.out.println(files);
}
// if run with "--debug logfile.txt" prints ["logfile.txt"]
}
}
```
提示: Spring Boot 還向 Spring Environment 注冊了一個 CommandLinePropertySource。 所以可以使用 @Value 注釋注入單個應用程序參數。
## 10. ApplicationRunner 和 CommandLineRunner 的使用
如果需要在 SpringApplication 啟動后運行某些特定代碼,可以實現 ApplicationRunner 或 CommandLineRunner 接口。 這兩個接口的工作方式相同,并提供一個 run 方法,該方法在 SpringApplication.run(... ) 完成之前調用。
注意: 該方式非常適合應在應用程序啟動之后但在開始接受流量之前運行的任務。
CommandLineRunner 接口提供對作為字符串數組的應用程序參數的訪問,而 ApplicationRunner 使用 ApplicationArguments 接口。 以下示例顯示了一個帶有 run 方法的 CommandLineRunner:
```
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) {
// Do something...
}
}
```
如果定義了多個必須按特定順序調用的 CommandLineRunner 或 ApplicationRunner bean,則可以另外實現 org.springframework.core.Ordered 接口或使用 org.springframework.core.annotation.Order 注釋。
## 11. 應用的退出
每個 SpringApplication 向 JVM 注冊一個關閉鉤子,以確保 ApplicationContext 在退出時正常關閉。 可以使用所有標準的 Spring 生命周期回調(例如 DisposableBean 接口或 @PreDestroy 注釋)。
此外,如果 bean 希望在調用 SpringApplication.exit() 時返回特定的退出代碼,它們可以實現 org.springframework.boot.ExitCodeGenerator 接口。 然后可以將此退出代碼傳遞給 System.exit() 以將其作為狀態代碼返回,如以下示例所示:
```
public class MyApplication {
@Bean
public ExitCodeGenerator exitCodeGenerator() {
return () -> 42;
}
public static void main(String[] args) {
System.exit(SpringApplication.exit(SpringApplication.run(MyApplication.class, args)));
}
}
```
此外,ExitCodeGenerator 接口可能由異常實現。 當遇到這樣的異常時,Spring Boot 會返回實現的 getExitCode() 方法提供的退出代碼。
## 12. 管理功能
通過指定` spring.application.admin.enabled `屬性為應用程序啟用與管理相關的功能。這將在平臺 MBeanServer 上公開 SpringApplicationAdminMXBean。 可以使用此功能遠程管理您的 Spring Boot 應用程序。 此功能也可用于任何服務包裝器實現。
提示: 如果想知道應用程序在哪個 HTTP 端口上運行,使用 local.server.port 鍵獲取屬性。
## 13. 應用程序啟動跟蹤
在應用程序啟動過程中,SpringApplication 和 ApplicationContext 執行許多與應用程序生命周期、bean 生命周期甚至處理應用程序事件相關的任務。 通過 ApplicationStartup,Spring Framework 允許您使用 StartupStep 對象跟蹤應用程序啟動順序。 可以收集這些數據用于分析目的,或者只是為了更好地了解應用程序啟動過程。
可以在設置 SpringApplication 實例時選擇 ApplicationStartup 實現。 例如,要使用 BufferingApplicationStartup,可以編寫:
```
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(MyApplication.class);
application.setApplicationStartup(new BufferingApplicationStartup(2048));
application.run(args);
}
}
```
第一個可用的實現 FlightRecorderApplicationStartup 由 Spring Framework 提供。 它將特定于 Spring 的啟動事件添加到 Java Flight Recorder 會話中,用于分析應用程序并將其 Spring 上下文生命周期與 JVM 事件(例如分配、GC、類加載......)相關聯。 配置完成后,可以通過在啟用Flight記錄器的情況下運行應用程序來記錄數據:
```
$ java -XX:StartFlightRecording:filename=recording.jfr,duration=10s -jar demo.jar
```
Spring Boot 附帶了 BufferingApplicationStartup 變體; 此實現旨在緩沖啟動步驟并將它們排入外部指標系統。 應用程序可以在任何組件中請求類型為 BufferingApplicationStartup 的 bean。
Spring Boot 還可以配置為公開一個啟動端點,該端點以 JSON 文檔的形式提供此信息。
*****
*****
如果您希望自動注冊這些偵聽器,無論應用程序的創建方式如何,您都可以將 META-INF/spring.factories 文件添加到您的項目中,并使用 org.springframework.context 引用您的偵聽器。 ApplicationListener 鍵,如下例所示:
也可以添加 META-INF/spring.factories 文件。 使用如下方式注冊:
```
org.springframework.context.ApplicationListener=com.example.project.MyListener
```
應用的事件是有順序的:
* 在實際開發中, 應用的事件一般較少使用
*
| | |
| --- | --- |
| addInitializers()| |
| addListeners | |
| addPrimarySources | |
| setAddCommandLineProperties | |
| setAddConversionService | |
| setAdditionalProfiles | |
| setAllowBeanDefinitionOverriding | |
| setBanner | |
| setBannerMode | |
| setDefaultProperties | |
| setEnvironment | |
| setHeadless | |
| setLazyInitialization | |
| setLogStartupInfo | |
| setWebApplicationType | |
| ... | |
具體參考:
https://docs.spring.io/spring-boot/docs/2.5.5/api/org/springframework/boot/SpringApplication.html
* 使用 Kubernetes Probes , 使用actuator
* 繼承 ApplicationAvailability 接口
1. 活動狀態(Liveness State), 內部狀況,不依賴外部檢查
2. 準備狀態(Readiness State),運行之后進入該狀態
3. 管理應用的可用狀態
可以將應用的準備狀態到處到文件, Kubernetes 的 “exec Probe” 就可以使用這個文件。
應用中斷無法恢復時,可以更新應用的狀態:
Spring Boot提供了 Kubernetes 的HTTPS 探測器來探測 Liveness和Readiness 狀態。可以參考:
https://docs.spring.io/spring-boot/docs/current/reference/html/deployment.html#deployment.cloud.kubernetes
- 前言
- 1. 基礎篇
- Spring Boot 介紹
- 如何創建Spring Boot項目
- Spring Boot基本使用
- 1. 系統構建
- 2. 代碼結構和開發
- 項目配置
- 配置文件
- pom.xml 配置說明
- 測試
- 測試介紹
- 測試注解
- 常見問題及解決
- Spring Boot測試示例
- Spring Boot Test 進行JPA 測試保存數據到數據庫
- 常見開發類
- Web
- HttpEntity
- CommandLineRunner
- 開發IDE
- Eclipse開發設置
- 開發知識點
- 項目相關路徑與資源獲取
- 2. 數據篇
- Spring操作數據庫的方式匯總
- Spring Data JPA
- Spring Boot操作數據庫的方式
- Spring Boot+JPA CriteriaBuilder查詢
- Spring Boot+JPA 有查詢條件的查詢
- CriteriaBuilder轉sql語句
- DAO
- Spring Boot+JPA 查詢數據方式與代碼演示
- Spring JPA 接口和類
- CrudRepository
- JPA Native Query(原生查詢)的緩存問題
- Eclipse下安裝EclipseLink進行JPA開發
- Eclipse Link or Hibernate
- 配置參考
- Spring Boot多數據源配置
- 錯誤解決
- ORA-00932: inconsistent datatypes: expected - got CLOB
- hibernate in 的list 大小不能超過1000
- java.lang.IllegalArgumentException: Cannot create TypedQuery for query with more than one return using requested result type
- ava.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate class [XXX]
- JPA 基礎
- Spring Jdbc 實現 Clob/Blob 類型字段的插入
- JPA Native Query(本地查詢)及查詢結果轉換
- JPA如何查詢部分字段
- JPA 主鍵策略
- JPA+EclipseLink+Oralce 通過GenerationType.AUTO 實現自增長字段
- JPA的persist() 和 merge() 方法的區別
- 關聯
- 批量更新
- JPA重要知識點
- JPA中實體的狀態
- 數據庫操作技術
- JPA二級緩存
- JPA3
- 分頁查詢
- Spring Boot+JPA 事務
- Spring Boot 數據源
- Spring Boot 3 整合 H2 快速示例
- Spring Boot+JPA+Oralce 配置
- Spring Boot+JPA不同類型數據庫的多數據源配置
- Spring Data JPA + Oracle
- Spring Boot + Oracle 處理Blob/Clob類型字段實例
- Spring Boot+JPA+Oracle Clob 類型字段查詢處理
- Spring Boot + JPA + Oracle 自增長字段實現示例
- 內存數據庫H2+Spring Boot
- 3. 實戰篇
- 項目創建和管理
- 基于Maven創建多模塊的Spring Boot項目
- 最佳實踐
- REST —Java對象的字符串屬性值轉換為JSON對象的布爾類型值
- Spring Boot 項目中Java對象的字符串類型屬性值轉換為JSON對象的布爾類型鍵值的解決方法及過程
- [在線API]Spring Boot+springfox-swagger2 之RESTful API自動生成和測試
- Spring Boot與JWT整合實現前后端分離的用戶認證之一
- 前后端分離的用戶驗證原理及Spring Boot + JWT的框架搭建(附完整的框架代碼)之一
- 前后端分離的用戶驗證原理及Spring Boot + JWT的框架搭建(附完整的框架代碼)之二
- SpringBoot應用中JSP的角色及整合
- Spring Boot項目中使用JSP實例
- Spring Boot 文件上傳功能實現與簡單示例
- Spring Boot+CKEditor 實現編輯器中的圖片上傳
- 開發注意事項
- 部署與維護
- SpringBoot項目在Gitee的控管步驟
- JSP如何獲取Spring Boot的配置屬性
- 錯誤頁面處理
- JPA相關
- Spring Boot + JPA 表和類的對應處理
- Spring Boot + JPA +MySQL 數據操作及示例環境搭建(手動建表)
- Spring Boot + JPA +MySQL 數據操作及示例環境搭建(自動建表)
- 基于Spring Boot + JPA +MySQL的JPA關聯查詢ManyToOne示例
- JPA的單向一對多關聯(oneToMany)實現示例(基于Spring Boot + JPA +MySQL,表自動維護)
- JPA的雙向一對多關聯(oneToMany)實現示例(基于Spring Boot + JPA +MySQL,表自動維護)
- JPA的雙向一對一關聯實現示例(基于Spring Boot + JPA +MySQL,表自動維護)
- 一次使用JUnit + JPA 實現數據Migrate的實例介紹
- Spring Boot整合H2內存數據庫配置及常見問題處理
- Spring Boot + Spring Data JPA 實現數據庫操作的標準示例
- REST
- Spring Boot 訪問HTTPS的url
- Spring Boot集成Log4j2
- Spring Boot + Ext JS 安全
- Spring Boot Web
- 內置服務器
- Spring Boot 中Filter的定義方式
- 開發工具
- Spring 開發利器之——Spring Tools 4
- Spring OAuth2+Basic
- Spring 緩存
- 快速實例
- Spring Security實戰
- Spring Boot OAuth2 快速入門示例
- Spring Boot 項目使用Spring Security防護CSRF攻擊實戰
- Spring Boot OAuth2 認證服務器搭建及授權碼認證演示
- 基于Spring OAuth2 之客戶端憑證模式演示
- 基于Spring OAuth2 之簡化模式演示
- 密碼模式
- 客戶端憑證
- 設置JWT Claim
- Client 數據庫配置
- Spring Boot+Security 實現Basic認證
- Spring Boot + WebLogic 12c 之Basic認證
- spring-security-oauth2-authorization-server
- 4. 專題篇
- 項目與屬性配置
- 外部化程序的配置
- 服務配置
- 不使用spring-boot-starter-parent作為Parent
- 數據庫配置
- Spring Boot 2.7.14+Oracle 11+WebLogic
- Spring Boot+Vaadin
- Spring Boot+Vaadin 14項目初始化
- Vaadin 導入JS和添加JS代碼段
- 常見及疑難問題解決
- Could not find artifact org.vaadin.artur:a-vaadin-helper:jar:1.6.2
- Spring Boot+Activiti
- Spring Boot + Activiti 工作流框架搭建
- Activiti 知識
- Spring Boot+Activiti開發注意點
- Activiti 代碼
- Spring Boot緩存
- Spring Boot Cache
- Spring Boot整合Redis快速入門實例
- 配置 JSON 序列器
- 錯誤解決篇
- Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to localhost:6379
- Spring Root+Cache+Redis 實戰
- Spring Boot+Redis 實現分布式緩存
- Spring Cloud + Redis 配置
- 主要類和方法
- 使用方式
- 緩存配置
- Redis Cache
- 緩存注解
- 類配置
- Spring Cloud
- 微服務架構
- 快速了解Spring Cloud
- Spring Cloud Eureka 最簡入門示例
- Spring Cloud Ribbon 負載均衡客戶端調用示例
- Spring Cloud Eureka注冊服務器集群配置
- Spring Cloud常見問題及解決
- Spring Cloud Eureka Server的部署與啟動
- 配置中心
- Spring Boot+HATEOAS
- HATEOAS概念
- Spring Boot+HATEOAS快速介紹與示例
- 開發說明
- Spring 安全
- Spring 框架RCE 安全漏洞
- Spring RCE 漏洞 CVE-2022-22965 的終極解決方案
- Spring Boot 跨域訪問實現方式
- 輕量級網關-反向代理
- Spring Security
- 基本使用
- 主要問題
- securityChain
- UserDetailsService
- 忽略請求URL
- 安全
- Spring Boot項目CSRF (跨站請求偽造)攻擊演示與防御
- Spring Boot CSRF 防御+Coverity
- 認證管理器-AuthenticationManager
- Spring Security開發介紹
- Spring Security 快速入門
- Spring Security 依賴導入
- Spring Security 用戶認證
- Spring CSRF 實現機制
- 實戰示例
- 入門示例
- Spring Security 常見問題
- Caused by: java.lang.IllegalArgumentException: realmName must be specified
- 總是報403錯誤
- Spring訪問http/https
- Spring RestTemplate 訪問https站點
- Spring Boot RestTemplate 忽略證書訪問https
- Spring Boot OAuth2 Client -客戶端模式 client credentials 獲取token
- OAuth2RestTemplate
- Spring Security OAuth 訪問OAuth2.0 的https站點
- Spring RestTemplate 忽略證書訪問https的OAuth2 認證站點
- Spring OAuth 2.0
- 授權服務器和資源服務器
- Spring 對 OAuth2.0的解決方案
- OAuth2 認證服務器
- jjwt+oauth
- Spring OAuth2 的認證
- Spring Boot實現訪問接口的Basic認證
- CORS
- Access-Control-Allow-Credentials
- Java JWT
- JWT
- 聲明-subject
- 安全基本知識
- BCrypt
- Spring LDAP
- Spring Boot LDAP 認證
- LDAP問題與解決
- javax.naming.PartialResultException: Unprocessed Continuation Reference(s);
- Spring IO
- 接口和類
- Resource
- 性能
- Web緩存
- Spring Web
- 如何添加Filter
- OncePerRequestFilter
- 得到請求地址和參數
- 應用上下文路徑
- 5. 開發參考
- 注解
- WebMvcAutoConfiguration
- JPA
- 如何加載 jar 中的注解類
- 1
- @EnableAsync
- 6. 常見問題
- bean named 'entityManagerFactory' that could not be found錯誤及解決
- invalid LOC header錯誤及解決
- No identifier specified for entity:
- Optional int parameter 'id' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type.
- Could not resolve view with name 'xxxx' in servlet with name 'dispatcherServlet'
- JSON parse error: Unrecognized field
- multipart/form-data;boundary=----WebKitFormBoundaryRAYPKeHKTYSNdzc1;charset=UTF-8' not supported
- 跨域 Access to XMLHttpRequest at ' xxxxx' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
- maven 下載問題
- Maven 無法下載Oracle 驅動解決
- Spring Boot常見面試題
- Spring Boot 訪問JSP主頁面出現下載頁面
- Spring Boot 面試題大全
- Spring Cloud相關問題
- java.lang.IllegalStateException: Request URI does not contain a valid hostname: http://eurekaclient_service/
- Spring JPA
- Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set。
- 同時排序和分頁查詢的數據不對
- No EntityManager with actual transaction available for current thread
- should be mapped with insert="false" update="false"
- java.lang.IllegalArgumentException: Not a managed type:XX
- java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: XX is not mapped
- org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only
- Transaction rolled back because it has been marked as rollback-only
- org.hibernate.LazyInitializationException: could not initialize proxy xxx - no Session
- [EclipseLink]The attribute [xxx] of class [xxx] is mapped to a primary key column in the database. Updates are not allowed.
- cannot simultaneously fetch multiple bags
- Spring Boot + Hibernate java.lang.IllegalArgumentException: Not an entity: class
- mvn spring-boot class file for javax.interceptor.InterceptorBinding not found
- sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
- Spring Boot返回的數據格式是XML 而不是JSON之原因探求的和解決
- Failed to parse multipart servlet request; nested exception is javax.servlet.ServletException: The request content-type is not a multipart/form-data
- WebSecurityConfigurerAdapter 過時及替代寫法
- consider increasing the maximum size of the cache
- java.lang.ClassCastException: org.springframework.context.annotation.AnnotationConfigApplicationContext cannot be cast to org.springframework.web.context.WebApplicationContext
- org.springframework.core.NestedIOException: ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn't supported yet
- Caused by: org.springframework.core.NestedIOException: ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn't supported yet
- Spring Boot測試無法運行問題解決(注入的組件為空)
- web.xml is missing and <failOnMissingWebXml> is set to true
- no main manifest attribute
- Refused to display 'http://localhost:8080/' in a frame because it set 'X-Frame-Options' to 'deny'.
- 問題模板
- Spring Security問題
- WebSecurityConfigurerAdapter過期了
- @EnableAuthorizationServer 已經廢棄
- com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [map type; class java.util.Map, [simple type, class java.lang.String] -> [simple type, class java.lang.Object]]: missing type id property '@class'
- Spring Web問題
- I/O error while reading input message; nested exception is java.io.IOException: Stream closed
- Filter讀取JSON參數之后, Spring無法自動封裝
- 部署到 WebLogic的問題
- 如何導入其他jar 的組件
- 類型轉換
- JSON 格式轉換
- Spring開發問題之org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class
- 7. 官方文檔翻譯篇
- Spring Framework參考文檔-V6.0.8
- 總覽
- 核心
- 測試-
- 數據訪問
- Web Servlet
- Web Reactive
- 整合
- 1. REST 客戶端
- 2.JMS(Java消息服務)
- 3. JMX
- 4. 郵件
- 5. 任務執行與排程
- 6. 緩存抽象
- 7. 監控支持
- 語言
- Spring Boot核心功能
- 1. SpringApplication 啟動引導類
- 2. 屬性配置
- 2.8 類型安全的屬性配置
- 3. Profile
- 4. 日志
- 5. 國際化
- 6. JSON
- 7. 任務執行和計劃
- 8. 測試
- 8.1 測試范圍依賴
- 8.2 測試Spring應用
- 8.3 測試Spring Boot應用
- 8.3.1 偵測Web應用的類型
- 8.3.2 偵測測試配置
- 8.3.3 排除測試配置
- 8.3.4 使用應用的參數
- 8.3.5 使用模擬環境測試
- 8.3.6 使用服務器進行測試
- 8.3.7 自定義WebTestClient
- 8.3.8 使用JMX
- 8.3.9 使用Metrics
- 8.3.10 模擬和窺探Beans
- 8.3.11 自動配置的測試
- 8.3.12 自動配置的JSON測試
- 8.3.13 Spring MVC測試的自動配置
- 8.3.14 Spring WebFlux 測試的自動配置
- 8.3.15 Cassandra 測試的自動配置
- 8.3.16 數據 JPA 測試的自動配置
- 8.4 測試工具類
- 9. 定制屬于你的自動配置
- 9.1 了解自動配置的Beans
- 9.2 定位自動配置的候選者
- 9.3 條件注釋
- 10. Kotlin 支持
- Spring Boot 其他功能
- 7. Web 應用的開發
- Spring MVC 框架
- Spring WebFlux 框架
- JAX-RS 和Jersey
- 內置 Servlet 容器支持
- 內置響應式服務器支持
- 響應式服務器資源配置
- 8. 優雅關閉
- 9. RSocket
- 10. 安全
- 11. 使用SQL 數據庫
- 11.2 JdbcTemplate 的使用
- 12. NoSQL技術
- 13. 緩存
- 14. 消息
- 15. 使用RestTemplate調用REST服務
- 16. 使用WebClient調用REST服務
- 17. 驗證
- 18. 發送郵件
- 19. 使用JTA實現分布式事務
- 20. 分布式內存-Hazelcast
- 21. 定時器Quartz Scheduler
- 22. 任務執行和計劃
- 23. Spring 整合
- 24. Spring 會話
- 25. 使用JMX 監控和管理
- 26. Testing 測試
- 27. WebSockets
- 28. Web Services
- 29. 創建自動配置
- 30. 對Kotlin 的支持
- 31. 容器
- Spring Boot開發指南 V3.1
- 入門
- Spring Boot應用升級
- 如何使用Spring Boot進行開發
- 核心功能
- Web-
- Data-數據
- IO
- 緩存
- 消息
- 容器
- 生產就緒功能
- 部署
- GraalVM Native Image Support
- Spring Boot命令行
- 構建工具插件
- 1. Spring Boot 應用
- 1.1 自定義錯誤分析器
- 1.2 自動配置的故障排除
- 1.3 啟動之前自定義環境(Environment)和應用上下文(ApplicationContext)
- Spring Data Redis -Version 3.0.5
- 前言
- Spring Redis 開發參考文檔
- 響應式 Redis 支持
- Redis集群
- Redis存儲庫
- Spring Security
- 參考
- Spring Authorization Server-0.4.2
- 概括
- 幫助
- Spring認證服務入門
- Spring Authorization Server-0.4.3
- 協議端點(Protocol Endpoints)
- OAuth2 授權端點
- 核心模型組件
- OAuth2TokenCustomizer
- 關聯知識
- JWK Set
- 默認端點
- JWT JWK
- OpenID Connect 1.0
- OAuth2
- 問題
- [invalid_request] OAuth 2.0 Parameter: redirect_uri
- [invalid_request] OAuth 2.0 Parameter: state
- There is no PasswordEncoder mapped for the id "null"
- 實際開發
- 8. 補充篇
- Jackson
- 資源
- 配置大全
- Spring Boot 與 Java 版本對應
- Java Web
- 如何在Filter中讀取JSON 類型的參數