1. 程式人生 > >手把手教你定製標準Spring Boot starter,真的很清晰

手把手教你定製標準Spring Boot starter,真的很清晰

寫在前面

我們每次構建一個 Spring 應用程式時,我們都不希望從頭開始實現具有「橫切關注點」的內容;相反,我們希望一次性實現這些功能,並根據需要將它們包含到任何我們要構建的應用程式中

橫切關注點

橫切關注點: 指的是一些具有橫越多個模組的行為 (來自維基百科的介紹)
說白了就是多個專案或模組都可以用到的內容,比如一個 SDK

在Spring Boot中,用於表示提供這種橫切關注點的模組的術語是 starter,通過依賴 starter 可以輕鬆使用其包含的一些功能特性,無論你的工作中是否會構建自己的 starter,你都要具有構建 「starter」的思想,本文將結合 Spring Boot 官方標準構建一個簡單的 starter

自定義 starter

在我們深入瞭解如何自定義 starter 之前,為了更好的理解我們每一步在幹什麼,以及 starter 是如何起作用的,我們先從巨集觀角度來看 starter 的結構組成到底是什麼樣的

通常一個完整的 starter 需要包含下面兩個元件:

  1. Auto-Configure Module
  2. 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 韓梅梅

總結

到這裡完整的 starter 開發就結束了,希望大家瞭解其構建過程,目錄結構及命名等標準,這樣有相應的業務需求時都可以開發自己的 starter 被其他人應用起來

starter 開發好了,別人可以手動新增依賴引入 starter 的相關功能,那我們如何像 Spring Initializr 一樣,通過下來選單選擇我們的 starter 呢,這樣直接初始化好整個專案,接下來的文章我們會模仿 Spring Initializr 自定義我們自的 Initializr

知識點說明

Dependency optinal

為什麼 Auto-Configure Module 的 dependency 都是 optional = true 呢?
這涉及到 Maven 傳遞性依賴的問題,詳情請看 Maven 依賴傳遞性透徹理解

spring.factories

Spring Boot 是如何載入這個檔案並找到我們的配置類的
下圖是 Spring Boot 應用程式啟動的呼叫棧的一部分,我添加了斷點:

開啟 SpringFactoriesLoader 類,映入眼簾的就是這個內容:

這兩張圖應該足夠說明問題了,是 SPI 的一種載入方式,更細節的內容請大家自己去發現吧

實際案例

這裡推薦檢視 mybatis-spring-boot-starter 這個非 Spring 官方的案例,從中我們:

  • 模仿其目錄結構
  • 模仿其設計理念
  • 模仿其編碼規範

另外,本文的案例我已上傳,公眾號回覆「demo」,開啟連結,檢視 customstarter 目錄下內容即可

靈魂追問

  1. 在生成 spring-autoconfigure-metadata.properties 檔案時,為什麼 @ConditionalOnProperty 的內容沒有被寫進去
  2. 如果我們要將依賴上傳至 remote central repository,你知道怎樣搭建自己的 maven repository 嗎?
  3. 你的燈還亮著嗎?

部落格已改版,提前發現更多精彩,請訪問: https://dayarch.top

歡迎持續關注公眾號:「日拱一兵」

  • 前沿 Java 技術乾貨分享
  • 高效工具彙總 | 回覆「工具」
  • 面試問題分析與解答
  • 技術資料領取 | 回覆「資料」

以讀偵探小說思維輕鬆趣味學習 Java 技術棧相關知識,本著將複雜問題簡單化,抽象問題具體化和圖形化原則逐步分解技術問題,技術持續更新,請持續關注......


相關推薦

手把手定製標準Spring Boot starter真的清晰

寫在前面 我們每次構建一個 Spring 應用程式時,我們都不希望從頭開始實現具有「橫切關注點」的內容;相反,我們希望一次性實現這些功能,並根據需要將它們包含到任何我們要構建的應用程式中 橫切關注點 橫切關注點: 指的是一些具有橫越多個模組的行為 (來自維基百科的介紹) 說白了就是多個專案或模組都可以用到的

寫Makefile(非常全面講解清晰

 Makefile 值得一提的是,在Makefile中的命令,必須要以[Tab]鍵開始。       什麼是makefile?或許很多Winodws的程式設計師都不知道這個東西,因為那些Windows的IDE都為你做了這個工作,但我覺

手把手深入理解Spring原始碼-spring開篇(中)

授人以魚不如授人以漁,《手把手教你深入理解Spring原始碼》專欄教你如何學習、思考、閱讀Spring框架,並應對其它開源框架不再畏懼。 接著上篇的文章講,上篇的文章講述了什麼是IOC,這篇講述什麼又是AOP? 一樣的在看這篇文章之前,大家不妨先花點時間思考一下。 1、AOP的設計原理

手把手整合maven+spring專案(3)

 在上一篇部落格裡我們講解了如何用maven專案整合Springmvc,今天我們將圍繞Spring Security 來介紹,Spring Security 提供了基於javaEE的企業應用軟體全面的安全服務,如果你的專案對於安全和訪問要求比較高,強烈輕易你在專案中使用Spring Sec

手把手整合maven+spring專案(2)

在上一篇部落格裡,講解了如何新建Maven專案,今天在我們將會在上一篇部落格的基礎上,整合springmvc,本篇部落格適合新手入門springmvc,下面將開始今天的正文; 第一步:新增包com.zds,並新增controller、dao、service各包, 然後,修改pom.xml,新

大神手把手寫一個頁面模板引擎只需20行Javascript代碼!

[1] 表達 最終 strong ice ali 開頭 syntax years 只用20行Javascript代碼就寫出一個頁面模板引擎的大神是AbsurdJS的作者,下面是他分享的全文,轉需。 不知道你有木有聽說過一個基於Javascript的Web頁面預處理器,叫做A

【Redis】手把手Windows中redis的下載安裝設定及啟動

文章目錄 1、系統環境 2、Redis下載 3、Redis在Windows中安裝 4、Redis啟動 5、環境變數設定

20T資料遷移經驗:手把手群暉NAS資料遷移黑裙暉通用!

原文網址:https://www.toutiao.com/a6630412335842329101/   2016年把Orico 陣列盒整成NAS,容量從8T增到20T,原本以為可以撐上個三五年,沒想到HIFI燒久了不僅錢包越來越癟,自動遇到Hao4K後就再也沒發現在家是一個儲存達

手把手在Word中設定大綱再也不用freestyle了

“你有freestyle嗎?”吳亦凡的一句話,讓很多人開始關注《中國有嘻哈》這個綜藝節目,也讓我們知道原來嘻哈是需要freestyle的。會freestyle的Rapper才是好Rapper,嘻哈歌手PG one也是在公演時展現了他的freestyle能力(雖然是因為忘詞)

【新手教程】手把手搭建騰訊雲伺服器圖文詳細教程

· 背景     暑假期間,愁著無聊但也不能荒廢學業吧,畢竟以後想靠技術混口飯吃!為了實施自己的計劃,特地挑了一個便宜的雲伺服器來用作自己的後臺;這不是學生狗沒錢嘛,所以我就挑了一個騰訊雲伺服器。雖說配置很低,但夠我們玩就行。因為想寫一個電商App,資料總不能從本地資料

手把手實現自定義Spring BootStarter

### 引言 上篇文章[《天天用SpringBoot,它的自動裝配原理卻說不出來》](https://mp.weixin.qq.com/s/TnofWzuaH-WDcfYVfp-UoA)我們有說`springBoot`的自動裝配怎麼實現的(建議最好先看下篇文章,因為前後有關係),這篇文章的話我們就自己來實現一

手把手手寫一個最簡單的 Spring Boot Starter

> 歡迎關注微信公眾號:「Java之言」技術文章持續更新,請持續關注...... > - 第一時間學習最新技術文章 > - 領取最新技術學習資料視訊 > - 最新網際網路資訊和麵試經驗 ## 何為 Starter ? 想必大家都使用過 SpringBoot,在 SpringBoot

手把手Spring Boot搭建一個線上檔案預覽系統!支援ppt、doc等多種型別檔案預覽

> 昨晚搭建環境都花了好一會時間,主要在浪費在了安裝 openoffice 這個依賴環境上(_Mac 需要手動安裝_)。 > > 然後,又一步一步功能演示,記錄,除錯專案,並且簡單研究了一下核心程式碼之後才把這篇文章寫完。 > > 另外,這篇文章我還會簡單分析一下專案核心程式碼。

手把手Spring Boot整合Mybatis Plus和Swagger2

#前言:如果你是初學者,請完全按照我的教程以及程式碼來搭建(文末會附上完整的專案程式碼包,你可以直接下載我提供的完整專案程式碼包然後自行體驗!),為了照顧初學者所以貼圖比較多,請耐心跟著教程來,希望這個專案Demo能給你一些幫助,如果覺得寫的還可以請給個關注和點贊,謝謝! #題外話:這是我第一篇用markdo

手把手如何恢復 /boot 目錄

恢復、/boot、grub.cfg、centos 6、centos 7前言 /boot目錄是一個系統啟動最重要的目錄,系統在上電自檢MBR引導之後,系統就要讀取/boot目錄下的文件。詳細的內容見:http://vinsent.blog.51cto.com/13116656/1963546。總之

手把手整合最優雅SSM框架 SpringMVC + Spring + MyBatis

                        &nbs

搭建Spring Boot專案包會!

目錄   前言 開始搭建最簡單的Spring Boot工程(下文會延伸) 第一步:開啟IDEA,新建專案 第二步:選擇Spring Initializr  第三步:設定專案基本資訊 第四步:為專案選擇依賴  第五步:建立專案資料夾 &

手把手搭建與整合SSM框架(文末附原始碼)(Spring MVC + Spring + MyBatis)

目錄 1.匯入jar包 2.專案目錄總覽 3.配置Spring IoC容器 4.連線資料庫配置 5.整合mybatis環境 5.1配置對映器  5.2建立Mapper介面 5.3建立資料庫表和實體類 6.整合Spring MVC 6.1配置&nb

如何搭建Spring環境?--手把手安裝Spring+搭建Spring開發環境。

手把手教你安裝Spring+搭建Spring開發環境。 步驟一:安裝eclipse 如果你已經下載安裝,可忽略此步。 就是這傢伙: 官網下載地址(64位):https://www.eclipse.org/downloads/download.phpfile=/oomp

spring架構---手把手ssm搭建架構

ssm框架指的是在web開發中使用spring,spring-mvc,MyBatis三種框架 Spring        Spring是一個開源框架,Spring是於2003 年興起的一個輕量級的Java 開發框架,由Rod