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

引言

上篇文章《每天用SpringBoot,它的自動裝配原理卻說不出來》咱們有說springBoot的自動裝配怎麼實現的(建議最好先看下篇文章,由於先後有關係),這篇文章的話咱們就本身來實現一個SpringBootstarter吧。廢話很少說咱們仍是直入主題吧。
在這裏插入圖片描述
什麼是Spring Boot Starter呢?咱們直接來看看官網是怎麼介紹的吧。html

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.java

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

  • 經過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實現各有差別,可是它們基本上都會使用到兩個相同的內容:ConfigurationPropertiesAutoConfiguration。由於Spring Boot提倡「約定大於配置」這一理念,因此咱們使用ConfigurationProperties來保存咱們的配置,而且這些配置均可以有一個默認值,即在咱們沒有主動覆寫原始配置的狀況下,默認值就會生效。除此以外,starterConfigurationProperties還使得全部的配置屬性被彙集到一個文件中(通常在resources目錄下的application.properties),這樣咱們就告別了Spring項目中XML地獄。
starter的出現幫把咱們把各類複雜的配置都封裝起來了,讓咱們真正的能夠達到了開箱即用。不只下降了咱們使用它的門檻,而且還大大提升了咱們的開發效率。正如前面所說《SpringBoot自動裝配》讓咱們有更多的時間去陪女友。程序員

實現本身的SpringBoot Starter

命名規範

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

What’s in a name
All 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.spring

大概意思是
官方的 starter 的命名格式爲 spring-boot-starter-{xxxx} 好比spring-boot-starter-activemq
第三方咱們本身的命名格式爲 {xxxx}-spring-boot-starter。好比mybatis-spring-boot-starter
若是咱們忽略這種約定,是否是會顯得咱們寫的東西不夠「專業「。數據庫

自定義一個Starter

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

  1. 引入pom
<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>
  1. 編寫配置文件

發短信咱們須要配置一些帳號信息,不一樣的短信供應商,帳戶信息是不同的,因此咱們須要定義一個XXXXProperties 來自動裝配這些帳戶信息。下面咱們就以騰訊雲和阿里雲兩家供應商爲例;springboot

@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 + '\'' +
                    '}';
        }
    }
}

若是須要在其餘項目中使用發送短信功能的話,咱們只須要在配置文件(application.yml)中配置SmsProperties 的屬性信息就能夠了。 好比:mybatis

sms:
  aliyun:
    pass-word: 12345
    user-name: java金融
    sign: 阿里雲
    url: http://aliyun.com/send
  tencent:
    pass-word: 6666
    user-name: java金融
    sign: 騰訊雲
    url: http://tencent.com/send

還記的@ConfigurationProperties註解裏面是否是有個prefix 屬性,咱們配置的這個屬性是sms,配置這個的主要一個做用的話是主要用來區別各個組件的參數。這裏有個小知識點須要注意下當咱們在配置文件輸入sms咱們的idea會提示這個sms有哪些屬性能夠配置,以及每一個屬性的註釋都有標記,建議的話註釋仍是寫英文,這樣會顯得你比較專業。
在這裏插入圖片描述
這個提示的話,是須要引入下面這個jar的。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

引入這個jar以後,咱們編譯以後就會在META-INF文件夾下面生成一個spring-configuration-metadata.json的文件。
在這裏插入圖片描述
咱們能夠看到這個文件其實 是根據SmsProperties類的成員屬性來生成的。

  1. 而後在編寫短信自動配置類:
@EnableConfigurationProperties(value = SmsProperties.class)
@Configuration
public class SmsAutoConfiguration  {
    /**
     *  阿里雲發送短信的實現類
     * @param smsProperties
     * @return
     */
    @Bean
    public AliyunSmsSenderImpl aliYunSmsSender(SmsProperties smsProperties){
       return new AliyunSmsSenderImpl(smsProperties.getAliyun());
    }
    /**
     * 騰訊雲發送短信的實現類
     * @param smsProperties
     * @return
     */
    @Bean
    public TencentSmsSenderImpl tencentSmsSender(SmsProperties smsProperties){
        return new TencentSmsSenderImpl(smsProperties.getTencent());
    }
}

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

public class AliyunSmsSenderImpl implements SmsSender {

    private SmsMessage smsMessage;

    public AliyunSmsSenderImpl(SmsMessage smsProperties) {
        this.smsMessage = smsProperties;
    }

    @Override
    public boolean send(String message) {
        System.out.println(smsMessage.toString()+"開始發送短信==》短信內容:"+message);
        return true;
    }
}
  1. 讓starter生效

starter集成應用有兩種方式:

  • 被動生效
    咱們首先來看下咱們熟悉的方式,經過SpringBootSPI的機制來去加載咱們的starter。咱們須要在META-INF下新建一個spring.factories文件keyorg.springframework.boot.autoconfigure.EnableAutoConfiguration, value是咱們的SmsAutoConfiguration 全限定名(記得去除先後的空格,不然會不生效)。
    在這裏插入圖片描述
  • 主動生效
    starter組件集成到咱們的Spring Boot應用時須要主動聲明啓用該starter才生效,經過自定義一個@Enable註解而後在把自動配置類經過Import註解引入進來。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({SmsAutoConfiguration.class})
public @interface EnableSms {
}

使用的時候須要在啓動類上面開啓這個註解。
在這裏插入圖片描述
5.打包,部署到倉庫
若是是本地的話,直接經過mvn install命令就能夠了。
若是須要部署到公司的倉庫話,這個就不說了。
6. 新建一個新的SpringBoot項目引入咱們剛寫的starter

<dependency>
            <groupId>com.workit.sms</groupId>
            <artifactId>sms-spring-boot-starter</artifactId>
            <version>0.0.1-SNAPSHOT</version>
      </dependency>

在項目配置文件配上短信帳號信息
在這裏插入圖片描述
測試代碼

@SpringBootApplication
@EnableSms
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("用騰訊雲發送短信");
    }

運行結果:

SmsMessage{userName='java金融', passWord='12345', sign='阿里雲', url='http://aliyun.com/send'}開始發送短信==》短信內容:用阿里雲發送短信
SmsMessage{userName='java金融', passWord='6666', sign='騰訊雲', url='http://tencent.com/send'}開始發送短信==》短信內容:用騰訊雲發送短信

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

總結

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

結束

  • 因爲本身才疏學淺,不免會有紕漏,假如你發現了錯誤的地方,還望留言給我指出來,我會對其加以修正。
  • 若是你以爲文章還不錯,你的轉發、分享、讚揚、點贊、留言就是對我最大的鼓勵。
  • 感謝您的閱讀,十分歡迎並感謝您的關注。
    站在巨人的肩膀上摘蘋果:
    https://www.cnblogs.com/tjudzj/p/8758391.html
    https://blog.springlearn.cn/posts/14644/
相關文章
相關標籤/搜索