您好,登錄后才能下訂單哦!
這篇文章主要介紹“如何定制標準Spring Boot starter”,在日常操作中,相信很多人在如何定制標準Spring Boot starter問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何定制標準Spring Boot starter”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
自定義 starter
在我們深入了解如何自定義 starter 之前,為了更好的理解我們每一步在干什么,以及 starter 是如何起作用的,我們先從宏觀角度來看 starter 的結構組成到底是什么樣的
通常一個完整的 starter 需要包含下面兩個組件:
Auto-Configure Module
Starter Module
如果你看下面這兩個組件的解釋有些抽象,大概了解一下,閱讀完該文章回看這里就會豁然開朗了
Auto-Configure Module
Auto-Configure Module (自動配置模塊) 是包含自動配置類的 Maven 或 Gradle 模塊。通過這種方式,我們可以構建可以自動貢獻于應用程序上下文的模塊,以及添加某個特性或提供對某個外部庫的訪問
Starter Module
Spring Boot Starter 是一個 Maven 或 Gradle 模塊,其唯一目的是提供 "啟動" 某個特性所需的所有依賴項。可以包含一個或多個 Auto-Configure Module (自動配置模塊)的依賴項,以及可能需要的任何其他依賴項。這樣,在Spring 啟動應用程序中,我們只需要添加這個 starter 依賴就可以使用其特性
: Spring 官方參考手冊建議將自動配置分離,并將每個自動配置啟動到一個獨立的 Maven 或 Gradle 模塊中,從而將自動配置和依賴項管理分離開來。如果你沒有建立一個供成千上萬用戶使用的開源庫,也可以將二者合并到一個 module 中
You may combine the auto-configuration code and the dependency management in a single module if you do not need to separate those two concerns
命名
來自 Spring 官方的 starter 都是 以 spring-boot-starter 開頭,比如:
spring-boot-starter-web
spring-boot-starter-aop
如果我們自定義 starter 功能名稱叫acme,那么我們的命名是這樣的:
acme-spring-boot-starter
acme-spring-boot-autoconfigure
如果 starter 中用到了配置 keys,也要注意不要使用 Spring Boot 使用的命名空間,比如(server,management,spring)
Parent Module 創建
先來全局看一下項目結構:
一級目錄結構:.
├── pom.xml ├── rgyb-spring-boot-autoconfigure ├── rgyb-spring-boot-sample └── rgyb-spring-boot-starter
二級目錄結構:.
├── pom.xml ├── rgyb-spring-boot-autoconfigure │ ├── pom.xml │ └── src ├── rgyb-spring-boot-sample │ ├── pom.xml │ └── src └── rgyb-spring-boot-starter ├── pom.xml └── src
創建一個空的父親 Maven Module,主要提供依賴管理,這樣 SubModule 不用單獨維護依賴版本號,來看 pom.xml 內容:
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> <!-- 添加其他全局依賴管理到這里,submodule默認不引入這些依賴,需要顯式的指定 --> </dependencyManagement>
Auto-Configure Module 構建
新建類 GreetingAutoConfiguration
@Configuration public class GreetingAutoConfiguration { @Bean public GreetingService greetingService(GreetingProperties greetingProperties){ return new GreetingService(greetingProperties.getMembers()); } }
我們用 @Configuration 注解標記類 GreetingAutoConfiguration,作為 starter 的入口點。這個配置包含了我們需要提供starter特性的所有 @Bean 定義,在本例中,為了簡單闡述問題,我們只將 GreetingService Bean 添加到應用程序上下文
GreetingService 內容如下:
@AllArgsConstructor public class GreetingService { private List<String> members = new ArrayList<>(); public void sayHello(){ members.forEach(s -> System.out.println("hello " + s)); } }
在 resources 目錄下新建文件 META-INF/spring.factories (如果目錄 META-INF 不存在需要手工創建),向文件寫入內容:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ top.dayarch.autoconfigure.GreetingAutoConfiguration
Spring 啟動時會在其 classpath 中所有的 spring.factoreis 文件,并加載里面的聲明配置,GreetingAutoConfiguration 類就緒后,我們的 Spring Boot Starter 就有了一個自動激活的入口點
到這里這個 "不完全的 starter" 已經可以使用了。但因為它是自動激活的,為了個讓其靈活可用,我們需要讓其按照我們的意愿來激活使用,所以我們需要條件注解來幫忙
條件配置
為類添加兩個條件注解:
@Configuration @ConditionalOnProperty(value = "rgyb.greeting.enable", havingValue = "true") @ConditionalOnClass(DummyEmail.class) public class GreetingAutoConfiguration { ... }
通過使用 @ConditionalOnProperty 注解,我們告訴 Spring,只有屬性 rgyb.greeting.enable 值被設置為 true 時,才將 GreetingAutoConfiguration (以及它聲明的所有 bean ) 包含到應用程序上下文中
通過使用 @ConditionalOnClass 注解,我們告訴Spring 只有類 DummyEmail.class 存在于 classpath 時,才將 GreetingAutoConfiguration (以及它聲明的所有 bean ) 包含到應用程序上下文中
多個條件是 and/與的關系,既只有滿足全部條件時,才會加載 GreetingAutoConfiguration
如果你對條件注解的使用還不是很明確,可以查看我之前的文章: @Conditional注解,靈活配置 Spring Boot
配置屬性管理
上面使用了 @ConditionalOnProperty 注解,實際 starter 中可能有非常多的屬性,所以我們需要將這些屬性集中管理:
@Data @ConfigurationProperties(prefix = "rgyb.greeting") public class GreetingProperties { /** * GreetingProperties 開關 */ boolean enable = false; /** * 需要打招呼的成員列表 */ List<String> members = new ArrayList<>(); }
我們知道這些屬性是要在 application.yml 中使用的,當我們需要使用這些屬性時,為了讓 IDE 給出更友好的提示,我們需要在 pom.xml 中添加依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
這樣當我們 mvn compile 時,會在生成一個名為 spring-configuration-metadata.json JSON 文件,文件內容如下:
生成的內容在接下來的內容中用到,且看
提升啟動時間
對于類路徑上的每個自動配置類,Spring Boot 必須計算 @Conditional… 條件值,用于決定是否加載自動配置及其所需的所有類,根據 Spring 啟動應用程序中 starter 的大小和數量,這可能是一個非常昂貴的操作,并且會影響啟動時間,為了提升啟動時間,我們需要在 pom.xml 中添加另外一個依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure-processor</artifactId> <optional>true</optional> </dependency>
這個注解會生成一個名為 spring-autoconfigure-metadata.properties Property 文件,其內容如下:
這樣,Spring Boot 在啟動期間讀取這些元數據,可以過濾出不滿足條件的配置,而不必實際檢查這些類,提升啟動速度
到這里關于 Auto-Configure Module 就構建完了,我們需要繼續完成 Starter Module 的構建
Starter Module 構建
Starter Module 的構建很簡單了,你可以認為它就是一個空 module,除了依賴 Auto-Configure Module,其唯一作用就是為了使用 starter 功能特性提供所有必須依賴,所以我們為 starter module 的 pom.xml 文件添加如下內容:
<dependencies> <dependency> <groupId>top.dayarch.learnings</groupId> <artifactId>rgyb-spring-boot-autoconfigure</artifactId> <version>1.0.0.RELEASE</version> </dependency> <!-- 在此處添加其他必要依賴,保證starter可用 --> </dependencies>
同樣在 resources 目錄下新建文件 META-INF/spring.providers , 其內容如下:
providers: rgyb-spring-boot-autoconfigure
該文件主要作用是說明 starter module 的依賴信息,多個依賴以逗號分隔就好,該文件不會影響 starter 的使用,可有可無
Starter Module 就可以這么簡單,將兩個 module 分別 mvn install 到本地 Maven Repository,接下來我們創建 sample module 引入這個 starter 依賴時就會從本地 Maven Repository 中拉取
創建 Sample Module
我們可以通過 Spring Initializr 正常初始化一個 Spring Boot 項目 (rgyb-spring-boot-sample),引入我們剛剛創建的 starter 依賴,在 sample pom.xml 中添加依賴:
<dependency> <groupId>top.dayarch.learnings</groupId> <artifactId>rgyb-spring-boot-starter</artifactId> <version>1.0.0.RELEASE</version> </dependency>
接下來配置 application.yml 屬性
rgyb: greeting: enable: true members: - 李雷 - 韓梅梅
在我們配置 YAML 的時候,會出現下圖的提示,這樣會更友好,當然為了規范,屬性描述最好也用英文描述,這里為了說明問題用了中文描述:
編寫測試類
我們編寫測試用例:
@Autowired(required = false) private GreetingService greetingService; @Test public void testGreeting() { greetingService.sayHello(); }
測試結果如下:
hello 李雷 hello 韓梅梅
知識點說明
Dependency optinal
為什么 Auto-Configure Module 的 dependency 都是 optional = true 呢?
這涉及到 Maven 傳遞性依賴的問題,詳情請看 Maven 依賴傳遞性透徹理解
spring.factories
Spring Boot 是如何加載這個文件并找到我們的配置類的
下圖是 Spring Boot 應用程序啟動的調用棧的一部分,我添加了斷點:
打開 SpringFactoriesLoader 類,映入眼簾的就是這個內容:
這兩張圖應該足夠說明問題了,是 SPI 的一種加載方式,更細節的內容請大家自己去發現吧
到此,關于“如何定制標準Spring Boot starter”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。