1. 概述
核心 Spring Boot 開發人員提供適用於大多數流行的開源項目的啓動器,但我們並不限於這些。
我們也可以編寫自定義的啓動器
如果我們在組織內使用內部庫,並且該庫計劃在 Spring Boot 環境中使用,則編寫啓動器是一個好做法。
這些啓動器使開發人員能夠避免冗長的配置並快速啓動他們的開發。但是,由於在後台發生了很多事情,因此有時很難理解註解或僅僅在 pom.xml 中包含依賴項如何啓用這麼多功能。
在本文中,我們將揭開 Spring Boot 的神秘面紗,瞭解其背後的運作原理。然後,我們將使用這些概念為我們自己的自定義庫創建一個啓動器。
2. 解密 Spring Boot 的自動配置
2.1 自動配置類
自 2.7 版本起,Spring Boot 在啓動時會在文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中查找自動配置導入,可以參考 spring-boot-autoconfigure 項目的 文件內容 作為示例。
...
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
...如我們所見,每一行文件都包含 Spring Boot 嘗試運行的完全限定名稱的自動配置類。
因此,根據此片段,Spring Boot 將嘗試運行 RabbitMQ、Cassandra、MongoDB 和 Hibernate 的所有配置類。
這些類是否實際運行取決於類路徑上是否存在依賴類。例如,如果 MongoDB 類在類路徑上找到,MongoAutoConfiguration 將運行,並且所有與 MongoDB 相關的 Bean 都會被初始化。
這種條件初始化是由 @ConditionalOnClass 註解啓用的。讓我們來看一下 MongoAutoConfiguration 類的代碼片段以瞭解其用法:
@Configuration
@ConditionalOnClass(MongoClient.class)
@EnableConfigurationProperties(MongoProperties.class)
@ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory")
public class MongoAutoConfiguration {
// configuration code
}現在,如果 MongoClient 已經在類路徑中可用 – 這個配置類將運行,並用一個 MongoClient 填充 Spring bean 工廠,該 MongoClient 使用默認配置初始化。
需要注意的是,如果 Spring Boot 版本低於 2.7,它會查找 META-INF/spring.factories 文件以進行自動配置導入。 類似於的示例可以在 spring-boot-autoconfigure 項目中找到:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration我們能看到該文件的格式是一個以逗號分隔的單行列表,指示自動配置類。如上例所示,我們可以使用反斜槓行延續來使單行列表更易於閲讀。
2.2. 自定義屬性來自 <em>application.properties</em> 文件
Spring Boot 使用一些預配置的默認值來初始化 Bean。為了覆蓋這些默認值,我們通常在 <em>application.properties</em> 文件中以特定名稱聲明它們。這些屬性會被 Spring Boot 容器自動拾取。
讓我們看看它是如何工作的。
在 <em>MongoAutoConfiguration</em> 代碼片段中,<em>@EnableConfigurationProperties</em> 註解與 `MongoProperties 類一起使用,該類充當自定義屬性的容器:
@ConfigurationProperties(prefix = "spring.data.mongodb")
public class MongoProperties {
private String host;
// other fields with standard getters and setters
}<p>前綴加上字段名,就構成了 <em >application.properties</em> 文件中屬性的名稱。因此,要為 MongoDB 設置 <em >host</em>,我們只需要在屬性文件中寫入以下內容:</p>
spring.data.mongodb.host = localhost同樣,可以使用屬性文件設置類中其他字段的值。
3. 創建自定義啓動器
根據第2部分的概念,要創建自定義啓動器,我們需要編寫以下組件:- 一個用於我們庫的自動配置類以及自定義配置的屬性類。
- 一個啓動器 pom,用於引入庫的依賴項和自動配置項目。
為了演示,我們創建了一個 簡單的問候庫,它將接受不同時間段的問候消息作為配置參數,並輸出問候消息。我們還將創建一個示例 Spring Boot 應用程序,以演示我們的自動配置和啓動器模塊的使用。
3.1. 自配置模塊
我們將我們的自動配置模塊命名為 greeter-spring-boot-autoconfigure。該模塊包含兩個主要類,即 GreeterProperties,它允許通過 application.properties 文件設置自定義屬性,以及 GreeterAutoConfiguration,它將為 greeter 庫創建 Bean。
讓我們來看這兩個類的代碼:
@ConfigurationProperties(prefix = "baeldung.greeter")
public class GreeterProperties {
private String userName;
private String morningMessage;
private String afternoonMessage;
private String eveningMessage;
private String nightMessage;
// standard getters and setters
}@Configuration
@ConditionalOnClass(Greeter.class)
@EnableConfigurationProperties(GreeterProperties.class)
public class GreeterAutoConfiguration {
@Autowired
private GreeterProperties greeterProperties;
@Bean
@ConditionalOnMissingBean
public GreetingConfig greeterConfig() {
String userName = greeterProperties.getUserName() == null
? System.getProperty("user.name")
: greeterProperties.getUserName();
// ..
GreetingConfig greetingConfig = new GreetingConfig();
greetingConfig.put(USER_NAME, userName);
// ...
return greetingConfig;
}
@Bean
@ConditionalOnMissingBean
public Greeter greeter(GreetingConfig greetingConfig) {
return new Greeter(greetingConfig);
}
}我們還需要將 GreeterAutoConfiguartion’s 的類名添加到 src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中:
com.baeldung.greeter.autoconfigure.GreeterAutoConfiguration
當然,如果使用較舊的 Spring Boot 版本(<2.7),則必須創建 src/main/resources/META-INF/spring.factories 文件,內容如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.baeldung.greeter.autoconfigure.GreeterAutoConfiguration在應用程序啓動時,GreeterAutoConfiguration 類將在類路徑中存在 Greeter 類的情況下運行。如果運行成功,它將通過 GreeterProperties 類讀取屬性,使用 GreeterConfig 和 Greeter Bean 填充 Spring 應用上下文。
@ConditionalOnMissingBean 註解將確保這些 Bean 僅在它們不存在時才創建。這允許開發人員通過在 @Configuration 類中定義自己的 Bean 來完全覆蓋自動配置的 Bean。
3.2. 創建 <em pom.xml</em>>
現在,讓我們創建一個啓動器 <em pom</em>>,它將引入自動配置模塊和 greeter 庫的依賴項。
根據命名約定,不由核心 Spring Boot 團隊管理的所有啓動器都應以庫名稱開頭,後跟後綴 <em>-spring-boot-starter</em>。因此,我們將我們的啓動器命名為 <em>greeter-spring-boot-starter</em>。
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>greeter-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>com.baeldung</groupId>
<artifactId>greeter-spring-boot-autoconfigure</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.baeldung</groupId>
<artifactId>greeter</artifactId>
<version>${greeter.version}</version>
</dependency>
</dependencies>
<properties>
<greeter.version>0.0.1-SNAPSHOT</greeter.version>
</properties>
</project>3.3. 使用 Starter
讓我們創建一個名為 greeter-spring-boot-sample-app 的應用程序,它將使用該 Starter。 在 pom.xml 中,我們需要將其添加為依賴項:
<dependency>
<groupId>com.baeldung</groupId>
<artifactId>greeter-spring-boot-starter</artifactId>
<version>${greeter-starter.version}</version>
</dependency>Spring Boot 將自動配置所有內容,並且我們有一個 Greeter Bean 已經準備好被注入和使用。
我們還可以通過在 application.properties 文件中定義它們,並使用 baeldung.greeter 前綴來更改 GreeterProperties 的默認值:
baeldung.greeter.userName=Baeldung
baeldung.greeter.afternoonMessage=Woha\ Afternoon最後,讓我們在我們的應用程序中使用 Greeter 組件:
@SpringBootApplication
public class GreeterSampleApplication implements CommandLineRunner {
@Autowired
private Greeter greeter;
public static void main(String[] args) {
SpringApplication.run(GreeterSampleApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
String message = greeter.greet();
System.out.println(message);
}
}4. 結論
在本快速教程中,我們重點介紹了自定義 Spring Boot 啓動器及其如何與自動配置機制協同工作,以消除大量的手動配置。