生活随笔
收集整理的這篇文章主要介紹了
自定义 Spring Boot Starter
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
一、引言
什么是Spring Boot Starter呢?我們直接來看看官網(wǎng)是怎么介紹的吧。
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
.
我們以上述官網(wǎng)的例子來進(jìn)行說明比如說我們需要在Spring 中適應(yīng)JPA來操作數(shù)據(jù)庫。在沒有springBoot-starter之前,我們需要引入jpa的步驟
通過maven 引入 jdbc 的依賴、以及 jpa 相關(guān)的各種依賴
編寫jpa相關(guān)的配置文件
網(wǎng)上各種查詢找資料進(jìn)行調(diào)試,調(diào)試的過程對于新手可能會有點奔潰會遇到各種奇奇怪怪的問題,jar包沖突啊,這個jar包下載不下來,缺少某個jar包。
終于在經(jīng)歷千辛萬苦,哼次哼次的解決各種問題之后終于把項目跑起來了,然后把這次整合jpa遇到的問題,以及整合的步驟都一一的詳細(xì)記錄下來。方便下次在需要整合jpa的時候直接copy就好了。我們以前在沒有starter之前是不是都是這么玩的。這樣的缺點是不是也非常顯著,比如過程復(fù)雜、需要不停的粘貼復(fù)制(不過這是程序員經(jīng)常干的事情了,也不在乎多一兩次了)、整合其它組件到自己的項目變的困難,效率低下。
二、SpringBoot Starter 的出現(xiàn)
我們可以看下SpringBoot 現(xiàn)在都為我們提供有哪些starter,這截圖了部分starter,更多的請點擊https://github.com/spring-projects/spring-boot/tree/master/spring-boot-project/spring-boot-starters
starter的實現(xiàn):雖然我們每個組件的starter實現(xiàn)各有差異,但是它們基本上都會使用到兩個相同的內(nèi)容:ConfigurationProperties和AutoConfiguration。 因為SpringBoot提倡“「約定大于配置」”這一理念,所以我們使用ConfigurationProperties來保存我們的配置,并且這些配置都可以有一個默認(rèn)值,即在我們沒有主動覆寫原始配置的情況下,默認(rèn)值就會生效。 除此之外,starter的ConfigurationProperties還使得所有的配置屬性被聚集到一個文件中(一般在resources目錄下的application.properties),這樣我們就告別了Spring項目中XML地獄。starter的出現(xiàn)幫把我們把各種復(fù)雜的配置都封裝起來了,讓我們真正的可以達(dá)到了開箱即用。不僅降低了我們使用它的門檻,并且還大大提高了我們的開發(fā)效率。
三、實現(xiàn)自己的 SpringBoot Starter
命名規(guī)范 在maven中,groupId代表著姓氏,artifactId代表著名字。Spring Boot也是有一個命名的建議的。所以名字是不能夠隨隨便便取得,可以按照官方的建議來取。
What’s
in a nameAll official starters follow a similar naming pattern
; spring-boot-starter-*, where * isa 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, thirdparty 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。 如果我們忽略這種約定,是不是會顯得我們寫的東西不夠“專業(yè)“。
自定義一個 Starter 下面我們就來實現(xiàn)一個自定義的發(fā)送短信的 starter,命名為sms-spring-boot-starter。
發(fā)短信我們需要配置一些賬號信息,不同的短信供應(yīng)商,賬戶信息是不一樣的,所以我們需要定義一個XXXXProperties 來自動裝配這些賬戶信息。下面我們就以騰訊云和阿里云兩家供應(yīng)商為例;
@ConfigurationProperties ( prefix
= "sms" )
@Data
public class SmsProperties { private SmsMessage aliyun
= new SmsMessage ( ) ; private SmsMessage tencent
= new SmsMessage ( ) ; @Data public static class SmsMessage { private String userName
; private String passWord
; private String sign
; private String url
; @Override public String toString ( ) { return "SmsMessage{" + "userName='" + userName
+ '\'' + ", passWord='" + passWord
+ '\'' + ", sign='" + sign
+ '\'' + ", url='" + url
+ '\'' + '}' ; } }
}
@EnableConfigurationProperties ( value
= SmsProperties . class )
@Configuration
public class SmsAutoConfiguration { @Bean public AliyunSmsSenderImpl aliYunSmsSender ( SmsProperties smsProperties
) { return new AliyunSmsSenderImpl ( smsProperties
. getAliyun ( ) ) ; } @Bean public TencentSmsSenderImpl tencentSmsSender ( SmsProperties smsProperties
) { return new TencentSmsSenderImpl ( smsProperties
. getTencent ( ) ) ; }
}
@ConditionalOnMissingBean ( { SmsMessage . class } )
public class AliyunSmsSenderImpl implements SmsSender { private final SmsMessage smsMessage
; public AliyunSmsSenderImpl ( SmsMessage smsProperties
) { this . smsMessage
= smsProperties
; } @Override public boolean send ( String message
) { System . out
. println ( smsMessage
. toString ( ) + "開始發(fā)送短信==》短信內(nèi)容:" + message
) ; return true ; }
}
starter集成應(yīng)用有兩種方式(被動生效和主動生效):
被動生效:通過SpringBoot的SPI的機(jī)制來去加載我們的 starter 我們需要在META-INF下新建一個spring.factories文件key為org.springframework.boot.autoconfigure.EnableAutoConfiguration, value是我們的SmsAutoConfiguration 全限定名(「記得去除前后的空格,否則會不生效」)。 主動生效:前提是先注銷spring.factories 主動生效在starter組件集成到我們的Spring Boot應(yīng)用時需要主動聲明啟用該starter才生效,通過自定義一個@Enable注解然后在把自動配置類通過Import注解引入進(jìn)來。
@Target ( { ElementType . TYPE
} )
@Retention ( RetentionPolicy . RUNTIME
)
@Documented
@Import ( { SmsAutoConfiguration . class } )
public @interface EnableSms {
}
使用的時候需要在啟動類上面開啟這個注解即可。 至此,我們的自定義starter已經(jīng)寫好了,接下來就是打包生成starter.jar。下面是工程完整結(jié)構(gòu): 注意,不是傳統(tǒng)的可運(yùn)行jar項目,所以沒有主入口
< ? xml version
= "1.0" encoding
= "UTF-8" ? >
< project xmlns
= "http://maven.apache.org/POM/4.0.0" xmlns
: xsi
= "http://www.w3.org/2001/XMLSchema-instance" xsi
: schemaLocation
= "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" > < modelVersion> 4.0 .0 < / modelVersion
> < parent> < groupId> org
. springframework
. boot
< / groupId
> < artifactId> spring
- boot
- starter
- parent
< / artifactId
> < version> 2.5 .3 < / version
> < relativePath
/ > < ! -- lookup parent from repository
-- > < / parent
> < groupId> com
. cristiano
< / groupId
> < artifactId> sms
- spring
- boot
- starter
< / artifactId
> < version> 0.0 .1 < / version
> < name> sms
- spring
- boot
- starter
< / name
> < description> sms
- spring
- boot
- starter
< / description
> < properties> < java. version> 1.8 < / java
. version
> < / properties
> < dependencies> < 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
> < optional> true < / optional
> < / dependency
> < / dependencies
> < build> < plugins> < plugin> < groupId> org
. springframework
. boot
< / groupId
> < artifactId> spring
- boot
- maven
- plugin
< / artifactId
> < ! -- 安裝到倉庫后,引用時不出現(xiàn) BOOT
- INF文件夾(會導(dǎo)致找不到相關(guān)類)
-- > < configuration> < skip> true < / skip
> < / configuration
> < / plugin
> < / plugins
> < / build
> < / project
>
重點注意:如果maven沒有這么配置,那么打包成jar的時候,會出現(xiàn)BOOT-INF文件夾,導(dǎo)致使用模塊的時候,找不到類,詳細(xì)參考這篇文章
< plugins> < plugin> < groupId> org
. springframework
. boot
< / groupId
> < artifactId> spring
- boot
- maven
- plugin
< / artifactId
> < ! -- 安裝到倉庫后,引用時不出現(xiàn) BOOT
- INF文件夾(會導(dǎo)致找不到相關(guān)類)
-- > < configuration> < skip> true < / skip
> < / configuration
> < / plugin
> < / plugins
>
Lifecycle下install就可以將模塊引用到本地倉庫了
四、測試Starter
< dependency> < groupId> com.cristiano
</ groupId> < artifactId> sms-spring-boot-starter
</ artifactId> < version> 0.0.1
</ version> </ dependency>
@SpringBootApplication
@EnableSms
public class TeststarterApplication { public static void main ( String [ ] args
) { SpringApplication . run ( TeststarterApplication . class , args
) ; }
}
配置(有提示) 測試 至此就結(jié)束了么?其實上面的例子加不加@EnableSms,都能正常打印信息,因為我們在Starter的spring.factories中已經(jīng)配置了自動配置類,屬于被動加載。
五、插拔式starter(基于主動依賴)
在SmsAutoConfiguration的原基礎(chǔ)上,加上以下注解后,重新install
@EnableConfigurationProperties ( value
= SmsProperties . class )
@Configuration
public class SmsAutoConfiguration { @Bean @ConditionalOnBean ( annotation
= EnableSms . class ) public AliyunSmsSenderImpl aliYunSmsSender ( SmsProperties smsProperties
) { return new AliyunSmsSenderImpl ( smsProperties
. getAliyun ( ) ) ; } @Bean public TencentSmsSenderImpl tencentSmsSender ( SmsProperties smsProperties
) { return new TencentSmsSenderImpl ( smsProperties
. getTencent ( ) ) ; }
}
@Target ( { ElementType . TYPE
} )
@Retention ( RetentionPolicy . RUNTIME
)
@Documented
@Import ( { SmsAutoConfiguration . class } )
public @interface EnableSms {
}
@SpringBootApplication
public class TeststarterApplication { public static void main ( String [ ] args
) { SpringApplication . run ( TeststarterApplication . class , args
) ; }
}
可以看到報錯,原因是AliyunSmsSenderImpl 沒有注冊到bean中,所以使用條件注解可以實現(xiàn)starter的插拔式應(yīng)用 正式使用
@EnableSms
@SpringBootApplication
public class TeststarterApplication { public static void main ( String [ ] args
) { SpringApplication . run ( TeststarterApplication . class , args
) ; }
}
@Autowired AliyunSmsSenderImpl aliyunSmsSender
; public void test ( ) { aliyunSmsSender
. send ( "from aliyun" ) ; }
配置
sms : aliyun : pass-word : aa
user-name : aa
url : www.aliyun.com
sign : alibaba
參考文章 參考文章
總結(jié)
以上是生活随笔 為你收集整理的自定义 Spring Boot Starter 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。