手把手教你實現自定義 Spring Boot 的 Starter

手把手教你實現自定義 Spring Boot 的 Starter

引言

我們就自己來實現一個SpringBoot的 starter吧。廢話不多說我們還是直入主題吧。

手把手教你實現自定義 Spring Boot 的 Starter

什麼是Spring Boot Starter呢?我們直接來看看官網是怎麼介紹的吧。

Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop shop for all the Spring and related technologies that you need without having to hunt through sample code and copy-paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access, include the spring-boot-starter-data-jpa dependency in your project.

納尼,一大堆的英文,這還有興趣接著往下看嗎?是不是看到這直接退出了。都到門口了,不進來喝杯茶再走嘛?看都看到這了還是接著繼續往下看吧。我們先不解釋這一段話是什麼意思,我們可以看看starter的出現給我們解決了什麼問題。我們還是以上述官網的例子來進行說明比如說我們需要在Spring 中適應JPA來操作數據庫。在沒有springBoot-starter之前,我們需要引入jpa的步驟

  • 通過maven 引入jdbc的依賴、以及jpa相關的各種依賴
  • 編寫jpa相關的配置文件
  • 網上各種查詢找資料進行調試,調試的過程對於新手可能會有點奔潰會遇到各種奇奇怪怪的問題,jar包衝突啊,這個jar包下載不下來,缺少某個jar包。
  • 終於在經歷千辛萬苦,哼次哼次的解決各種問題之後終於把項目跑起來了,然後把這次整合jpa遇到的問題,以及整合的步驟都一一的詳細記錄下來。方便下次在需要整合jpa的時候直接copy就好了。我們以前在沒有starter之前是不是都是這麼玩的。這樣的缺點是不是也非常顯著,比如過程複雜、需要不停的粘貼複製(不過這是程序員經常乾的事情了,也不在乎多一兩次了)、整合其它組件到自己的項目變的困難,效率低下。這也就造成了996的程序員比較多了(晚上就不能夠回去69了)。
手把手教你實現自定義 Spring Boot 的 Starter


SpringBoot Starter的出現

我們可以看下SpringBoot 現在都為我們提供有哪些starter,我這邊這截圖了部分starter,更多的請點擊https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-starters

手把手教你實現自定義 Spring Boot 的 Starter

starter的實現:雖然我們每個組件的starter實現各有差異,但是它們基本上都會使用到兩個相同的內容:ConfigurationProperties和AutoConfiguration。因為Spring Boot提倡“「約定大於配置」”這一理念,所以我們使用ConfigurationProperties來保存我們的配置,並且這些配置都可以有一個默認值,即在我們沒有主動覆寫原始配置的情況下,默認值就會生效。除此之外,starter的ConfigurationProperties還使得所有的配置屬性被聚集到一個文件中(一般在resources目錄下的application.properties),這樣我們就告別了Spring項目中XML地獄。starter的出現幫把我們把各種複雜的配置都封裝起來了,讓我們真正的可以達到了開箱即用。不僅降低了我們使用它的門檻,並且還大大提高了我們的開發效率。正如前面所說《SpringBoot自動裝配》讓我們有更多的時間去陪女朋友。

實現自己的SpringBoot Starter

命名規範

如果你快有孩子了,出生前你比較急的一定是起個名字。孩子的姓名標識著你和你愛人的血統,一定不會起隔壁老王的姓氏,肯定會招來異樣的眼光。在maven中,groupId代表著姓氏,artifactId代表著名字。Spring Boot也是有一個命名的建議的。所以名字是不能夠隨隨便便取得,可以按照官方的建議來取。

What’s in a nameAll official starters follow a similar naming pattern; spring-boot-starter-*, where * is a particular type of application. This naming structure is intended to help when you need to find a starter. The Maven integration in many IDEs lets you search dependencies by name. For example, with the appropriate Eclipse or STS plugin installed, you can press ctrl-space in the POM editor and type “spring-boot-starter” for a complete list.As explained in the “Creating Your Own Starter” section, third party starters should not start with spring-boot, as it is reserved for official Spring Boot artifacts. Rather, a third-party starter typically starts with the name of the project. For example, a third-party starter project called thirdpartyproject would typically be named thirdpartyproject-spring-boot-starter.

大概意思是官方的 starter 的命名格式為 spring-boot-starter-{xxxx} 比如spring-boot-starter-activemq第三方我們自己的命名格式為 {xxxx}-spring-boot-starter。比如mybatis-spring-boot-starter。如果我們忽略這種約定,是不是會顯得我們寫的東西不夠“專業“。

自定義一個Starter

下面我們就來實現一個自定義的發送短信的starter,命名為sms-spring-boot-starter。

1「引入pom

<code> 

<

dependency

>

<

groupId

>

org.springframework.boot

groupId

>

<

artifactId

>

spring-boot-starter

artifactId

>

dependency

>

<

dependency

>

<

groupId

>

org.springframework.boot

groupId

>

<

artifactId

>

spring-boot-configuration-processor

artifactId

>

<

optional

>

true

optional

>

dependency

>

<

dependency

>

<

groupId

>

org.projectlombok

groupId

>

<

artifactId

>

lombok

artifactId

>

<

version

>

1.16.18

version

>

<

scope

>

provided

scope

>

dependency

>

/<code>

2「編寫配置文件」

發短信我們需要配置一些賬號信息,不同的短信供應商,賬戶信息是不一樣的,所以我們需要定義一個XXXXProperties 來自動裝配這些賬戶信息。下面我們就以騰訊雲和阿里雲兩家供應商為例;

<code> (prefix = 

"sms"

)

public

class

SmsProperties {

private

SmsMessage aliyun =

new

SmsMessage();

private

SmsMessage tencent =

new

SmsMessage();

public

static

class

SmsMessage{

private

String

userName;

private

String

passWord;

private

String

sign;

private

String

url;

public

String

toString() {

return

"SmsMessage{"

+

"userName='"

+ userName +

'\''

+

", passWord='"

+ passWord +

'\''

+

", sign='"

+ sign +

'\''

+

", url='"

+ url +

'\''

+

'}'

; } } }/<code>

如果需要在其他項目中使用發送短信功能的話,我們只需要在配置文件(application.yml)中配置SmsProperties 的屬性信息就可以了。 比如:

<code>

sms

:

aliyun

:

pass-word

:

12345

user-name

: java金融

sign

: 阿里雲

url

:

http

:

tencent

:

pass-word

:

6666

user-name

: java金融

sign

: 騰訊雲

url

:

http

:/<code>

還記的@ConfigurationProperties註解裡面是不是有個prefix 屬性,我們配置的這個屬性是sms,配置這個的主要一個作用的話是主要用來區別各個組件的參數。這裡有個小知識點需要注意下當我們在配置文件輸入sms我們的idea會提示這個sms有哪些屬性可以配置,以及每個屬性的註釋都有標記,建議的話註釋還是寫英文,這樣會顯得你比較專業。

手把手教你實現自定義 Spring Boot 的 Starter

這個提示的話,是需要引入下面這個jar的。

<code>

<

dependency

>

<

groupId

>

org.springframework.boot

groupId

>

<

artifactId

>

spring-boot-configuration-processor

artifactId

>

<

optional

>

true

optional

>

dependency

>

/<code>



引入這個jar之後,我們編譯之後就會在META-INF文件夾下面生成一個spring-configuration-metadata.json的文件。

手把手教你實現自定義 Spring Boot 的 Starter

我們可以看到這個文件其實 是根據SmsProperties類的成員屬性來生成的。

3「然後編寫短信自動配置類:」

<code> 
 

public

class

SmsAutoConfiguration

{

public

AliyunSmsSenderImpl aliYunSmsSender(SmsProperties smsProperties){

return

new AliyunSmsSenderImpl(smsProperties.getAliyun()); }

public

TencentSmsSenderImpl tencentSmsSender(SmsProperties smsProperties){

return

new TencentSmsSenderImpl(smsProperties.getTencent()); } }/<code>

編寫我們的發送短信實現類:

<code>

public

class

AliyunSmsSenderImpl

implements

SmsSender

{

private

SmsMessage smsMessage;

public

AliyunSmsSenderImpl

(SmsMessage smsProperties)

{

this

.smsMessage = smsProperties; }

public

boolean

send

(String message)

{ System.out.println(smsMessage.toString()+

"開始發送短信==》短信內容:"

+message);

return

true

; } }/<code>



4「讓starter生效」

starter集成應用有兩種方式:

  • 被動生效我們首先來看下我們熟悉的方式,通過SpringBoot的SPI的機制來去加載我們的starter。我們需要在META-INF下新建一個spring.factories文件key為org.springframework.boot.autoconfigure.EnableAutoConfiguration, value是我們的SmsAutoConfiguration 全限定名(「記得去除前後的空格,否則會不生效」)。
手把手教你實現自定義 Spring Boot 的 Starter

  • 主動生效在starter組件集成到我們的Spring Boot應用時需要主動聲明啟用該starter才生效,通過自定義一個@Enable註解然後在把自動配置類通過Import註解引入進來。
<code>

@Target

({ElementType.TYPE})

@Retention

(RetentionPolicy.RUNTIME)

@Documented

@Import

({SmsAutoConfiguration.class}) public

@interface

EnableSms { }/<code>

使用的時候需要在啟動類上面開啟這個註解。

手把手教你實現自定義 Spring Boot 的 Starter

5.「打包,部署到倉庫」如果是本地的話,直接通過mvn install命令就可以了。如果需要部署到公司的倉庫話,這個就不說了。

6. 「新建一個新的SpringBoot項目引入我們剛寫的starter

<code>

<

dependency

>

<

groupId

>

com.workit.sms

groupId

>

<

artifactId

>

sms-spring-boot-starter

artifactId

>

<

version

>

0.0.1-SNAPSHOT

version

>

dependency

>

/<code>

在項目配置文件配上短信賬號信息

手把手教你實現自定義 Spring Boot 的 Starter

測試代碼

<code> 
 

public

class

AutoconfigApplication

{

public

static

void

main

(String[] args)

{ ConfigurableApplicationContext applicationContext = SpringApplication.run(AutoconfigApplication

.

class

,

args

)

; AliyunSmsSenderImpl aliyunSmsSender = applicationContext.getBean(AliyunSmsSenderImpl

.

class

)

; aliyunSmsSender.send(

"用阿里雲發送短信"

); TencentSmsSenderImpl tencentSmsSender = applicationContext.getBean(TencentSmsSenderImpl

.

class

)

; tencentSmsSender.send(

"用騰訊雲發送短信"

); }/<code>

運行結果:

<code>SmsMessage{userName=

'java金融'

, passWord=

'12345'

, sign=

'阿里雲'

, url=

'http://aliyun.com/send'

}開始發送短信==》短信內容:用阿里雲發送短信 SmsMessage{userName=

'java金融'

, passWord=

'6666'

, sign=

'騰訊雲'

, url=

'http://tencent.com/send'

}開始發送短信==》短信內容:用騰訊雲發送短信/<code>



至此的話我們自定義的一個starter就已經完成了,這個starter只是一個演示的demo,代碼有點粗糙,項目結構也有點問題。重點看下這個實現原理就好。趕緊動動小手去實現一個自己的starter吧。

總結

  • SpringBoot starter的出現,讓我們項目中集成其他組件變得簡單。它把簡單給了別人,把複雜留給了自己。“犧牲小我,成就大我”的思想還是值得學習的。平時我們工作中,比如要開發一個組件、或者一個工具類,也應該儘可能的讓使用方可以做到無腦使用,不要搞的太複雜,又能讓使用者可以靈活擴展。


分享到:


相關文章: