Spring Boot (一): Spring Boot starter自定義

前些日子在公司接觸了spring bootspring 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.passwordstorage.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)注虱咧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锚国,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子血筑,更是在濱河造成了極大的恐慌,老刑警劉巖豺总,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件喻喳,死亡現(xiàn)場離奇詭異,居然都是意外死亡表伦,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盈魁,“玉大人,你說我怎么就攤上這事赤套∩耗ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵剔氏,是天一觀的道長竹祷。 經(jīng)常有香客問我,道長塑陵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任阻桅,我火速辦了婚禮,結(jié)果婚禮上嫂沉,老公的妹妹穿的比我還像新娘。我一直安慰自己瓦胎,他們只是感情好尤揣,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著负芋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旧蛾。 梳的紋絲不亂的頭發(fā)上蠕嫁,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音病袄,去河邊找鬼赘阀。 笑死益缠,一個胖子當(dāng)著我的面吹牛基公,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播胰伍,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼酸休,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了菩咨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤抽米,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后是目,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體标捺,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年嗤疯,在試婚紗的時候發(fā)現(xiàn)自己被綠了闺兢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡脚囊,死狀恐怖桐磁,靈堂內(nèi)的尸體忽然破棺而出悔耘,到底是詐尸還是另有隱情我擂,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站郎任,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏分井。R本人自食惡果不足惜霉猛,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瘫辩。 院中可真熱鬧,春花似錦伐厌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荡澎。三九已至晤锹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間抖甘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工薇宠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留艰额,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓柄沮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親狱意。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容