前些日子在公司接觸了spring boot
和spring cloud
,有感于其大大簡化了spring的配置過程寇蚊,十分方便使用者快速構(gòu)建項目祷嘶,而且擁有豐富的starter供開發(fā)者使用败许。但是由于其自動化配置的原因见秤,往往導(dǎo)致出現(xiàn)問題抑党,新手無法快速定位問題崎脉。這里我就來總結(jié)一下spring boot 自定義starter的過程,相信大家看完這篇文章之后,能夠?qū)?code>spring boot starter的運行原理有了基本的認識图甜。
?為了節(jié)約你的時間碍粥,本篇文章的主要內(nèi)容有:
- spring boot starter的自定義
- spring boot auto-configuration的兩種方式,spring.factories和注解
- Conditional注解的使用
引入pom依賴
相信接觸過spring boot的開發(fā)者都會被其豐富的starter所吸引,如果你想給項目添加redis支持具则,你就可以直接引用spring-boot-starter-redis
即纲,如果你想使項目微服務(wù)化,你可以直接使用spring-cloud-starter-eureka
博肋。這些都是spring boot所提供的便利開發(fā)者的組件低斋,大家也可以自定義自己的starter并開源出去供開發(fā)者使用。
?創(chuàng)建自己的starter項目需要maven依賴是如下所示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>1.4.4.RELEASE</version>
</dependency>
核心配置類StorageAutoConfigure
構(gòu)建starter的關(guān)鍵是編寫一個裝配類匪凡,這個類可以提供該starter核心bean膊畴。這里我們的starter提供一個類似redis
的鍵值存儲功能的bean,我們叫它為StorageService
病游。負責(zé)對這個bean進行自動化裝配的類叫做StorageAutoConfigure
唇跨。保存application.properties配置信息的類叫做StorageServiceProperties
。這三種類像是鐵三角一樣衬衬,你可以在很多的spring-boot-starter
中看到他們的身影买猖。
?我們首先來看StorageAutoConfigure
的定義。
@Configuration
@ConditionalOnClass(StorageService.class)
@EnableConfigurationProperties(StorageServiceProperties.class)
public class StorageAutoConfigure {
@Autowired
private StorageServiceProperties properties;
@Bean
@ConditionalOnMissingBean(StorageService.class)
@ConditionalOnProperty(prefix = "storage.service", value = "enabled", havingValue = "true")
StorageService exampleService() {
return new StorageService(properties);
}
}
我們首先講一下源碼中注解的作用玉控。
-
@Configuration
,被該注解注釋的類會提供一個或則多個@bean
修飾的方法并且會被spring容器處理來生成bean definitions
狮惜。 -
@bean
注解是必須修飾函數(shù)的高诺,該函數(shù)可以提供一個bean
。而且該函數(shù)的函數(shù)名必須和bean的名稱一致虱而,除了首字母不需要大寫筏餐。 -
@ConditionalOnClass
注解是條件判斷的注解,表示對應(yīng)的類在classpath目錄下存在時魁瞪,才會去解析對應(yīng)的配置文件。 -
@EnableConfigurationProperties
注解給出了該配置類所需要的配置信息類佩番,也就是StorageServiceProperties
類,這樣spring容器才會去讀取配置信息到StorageServiceProperties
對象中罢杉。 -
@ConditionalOnMissingBean
注解也是條件判斷的注解,表示如果不存在對應(yīng)的bean條件才成立贡歧,這里就表示如果已經(jīng)有StorageService
的bean了滩租,那么就不再進行該bean的生成利朵。這個注解十分重要,涉及到默認配置和用戶自定義配置的原理绍弟。也就是說用戶可以自定義一個StorageService
的bean,這樣的話,spring容器就不需要再初始化這個默認的bean了而叼。 -
ConditionalOnProperty
注解是條件判斷的注解豹悬,表示如果配置文件中的響應(yīng)配置項數(shù)值為true,才會對該bean進行初始化葵陵。
看到這里瞻佛,大家大概都明白了StorageAutoConfigure
的作用了吧,spring容器會讀取相應(yīng)的配置信息到StorageServiceProperties
中伤柄,然后依據(jù)調(diào)節(jié)判斷初始化StorageService這個bean。集成了該starter
的項目就可以直接使用StorageService
來存儲鍵值信息了秤朗。
配置信息類StorageServiceProperties
存儲配置信息的類StorageServiceProperties
很簡單蔗彤,源碼如下所示:
@ConfigurationProperties("storage.service")
public class StorageServiceProperties {
private String username;
private String password;
private String url;
......
//一系列的getter和setter函數(shù)
}
@ConfigurationProperties
注解就是讓spring容器知道該配置類的配置項前綴是什么疯兼,上述的源碼給出的配置信息項有storage.service.username
,storage.service.password
和storage.service.url
贫途,類似于數(shù)據(jù)庫的host和用戶名密碼。這些配置信息都會由spring容器從application.properties
文件中讀取出來設(shè)置到該類中丢早。
starter提供功能的StorageService
StorageService
類是提供整個starter的核心功能的類,也就是提供鍵值存儲的功能傀缩。
public class StorageService {
private Logger logger = LoggerFactory.getLogger(StorageService.class);
private String url;
private String username;
private String password;
private HashMap<String, Object> storage = new HashMap<String, Object>();
public StorageService(StorageServiceProperties properties) {
super();
this.url = properties.getUrl();
this.username = properties.getUsername();
this.password = properties.getPassword();
logger.debug("init storage with url " + url + " name: " + username + " password: " + password);
}
public void put(String key, Object val) {
storage.put(key, val);
}
public Object get(String key) {
return storage.get(key);
}
}
注解配置和spring.factories
?自定義的starter
有兩種方式來通知spring容器導(dǎo)入自己的auto-configuration類农猬,也就是本文當(dāng)中的StorageAutoConfigure
類。
?一般都是在starter
項目的resources/META-INF
文件夾下的spring.factories文件中加入需要自動化配置類的全限定名稱慷垮。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=starter.StorageAutoConfigure
?spring boot
項目中的EnableAutoConfigurationImportSelector
會自動去每個jar的相應(yīng)文件下查看spring.factories文件內(nèi)容揍堕,并將其中的類加載出來在auto-configuration過程中進行配置。而EnableAutoConfigurationImportSelector
在@EnableAutoConfiguration
注解中被import
衩茸。
?第一種方法只要是引入該starter芹血,那么spring.factories中的auto-configuration類就會被裝載楞慈,但是如果你希望有更加靈活的方式,那么就使用自定義注解來引入裝配類抖部。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(StorageAutoConfigure.class)
@Documented
public @interface EnableStorage {
}
?有了這個注解,你可以在你引入該starter的項目中使用該注解乡恕,通過@import
注解俯萎,spring容器會自動加載StorageAutoConfigure
并自動化進行配置傲宜。
后記
?上述只是關(guān)于spring boot starter最為簡單的定制和原理分析夫啊,后續(xù)我準備研究一下spring cloud stream
的源碼,主要是因為工作上一直在使用這個框架撇眯。請大家繼續(xù)關(guān)注虱咧。