引言
我們就自己來實現一個SpringBoot的 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了)。
SpringBoot Starter的出現
我們可以看下SpringBoot 現在都為我們提供有哪些starter,我這邊這截圖了部分starter,更多的請點擊https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-starters
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.bootgroupId
><
artifactId
>spring-boot-starterartifactId
>dependency
><
dependency
><
groupId
>org.springframework.bootgroupId
><
artifactId
>spring-boot-configuration-processorartifactId
><
optional
>trueoptional
>dependency
><
dependency
><
groupId
>org.projectlombokgroupId
><
artifactId
>lombokartifactId
><
version
>1.16.18version
><
scope
>providedscope
>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有哪些屬性可以配置,以及每個屬性的註釋都有標記,建議的話註釋還是寫英文,這樣會顯得你比較專業。
這個提示的話,是需要引入下面這個jar的。
<code><
dependency
><
groupId
>org.springframework.bootgroupId
><
artifactId
>spring-boot-configuration-processorartifactId
><
optional
>trueoptional
>dependency
>/<code>
引入這個jar之後,我們編譯之後就會在META-INF文件夾下面生成一個spring-configuration-metadata.json的文件。
我們可以看到這個文件其實 是根據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 全限定名(「記得去除前後的空格,否則會不生效」)。
- 主動生效在starter組件集成到我們的Spring Boot應用時需要主動聲明啟用該starter才生效,通過自定義一個@Enable註解然後在把自動配置類通過Import註解引入進來。
<code>@Target
({ElementType.TYPE})@Retention
(RetentionPolicy.RUNTIME)@Documented
@Import
({SmsAutoConfiguration.class}) public@interface
EnableSms { }/<code>
使用的時候需要在啟動類上面開啟這個註解。
5.「打包,部署到倉庫」如果是本地的話,直接通過mvn install命令就可以了。如果需要部署到公司的倉庫話,這個就不說了。
6. 「新建一個新的SpringBoot項目引入我們剛寫的starter
」<code><
dependency
><
groupId
>com.workit.smsgroupId
><
artifactId
>sms-spring-boot-starterartifactId
><
version
>0.0.1-SNAPSHOTversion
>dependency
>/<code>
在項目配置文件配上短信賬號信息
測試代碼
<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的出現,讓我們項目中集成其他組件變得簡單。它把簡單給了別人,把複雜留給了自己。“犧牲小我,成就大我”的思想還是值得學習的。平時我們工作中,比如要開發一個組件、或者一個工具類,也應該儘可能的讓使用方可以做到無腦使用,不要搞的太複雜,又能讓使用者可以靈活擴展。
關鍵字: SmsMessage public 我們