SpringBoot自定義starter及自動配置

  • 2019 年 11 月 7 日
  • 筆記

SpringBoot的核心就是自動配置,而支持自動配置的是一個個starter項目。除了官方已有的starter,用戶自己也可以根據規則自定義自己的starter項目。

自定義starter條件

自動化配置需滿足以下條件:

  • 根據條件檢查classpath下對應的類,也就是說需要提供對應可檢查的類;
  • 當滿足條件時能夠生成定義的Bean,並註冊到容器中去;
  • 能夠自動配置項目所需要的配置;

自定義spring boot starter

這裡通過maven項目管理工具進行starter的創建。首先我們需要創建一個簡單的maven項目。這裡我們以集成某短訊服務為例,來創建一個項目。

創建maven項目

創建一個簡單的maven項目,具體步驟省略。可通過intellj idea等IDE進行創建,也可通過maven命令進行創建。

目錄結構如下:

.  ├── pom.xml  ├── spring-boot-starter-msg.iml  └── src      ├── main      └── test

在pom.xml中引入SpringBoot自動化配置依賴spring-boot-autoconfigure:

<dependency>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-autoconfigure</artifactId>      <version>2.1.5.RELEASE</version>  </dependency>

定義Service服務類

定義Service服務類,有兩個作用,一個為引入的項目本省的功能性服務,另外一個用來springboot自動配置時的判斷依據。

這裡定義一個MsgService的類。

package com.secbro2.msg;    import com.secbro2.utils.HttpClientUtils;    public class MsgService {        /**       * 訪問發送短訊的url地址       */      private String url;        /**       * 短訊服務商提供的請求keyId       */      private String accessKeyId;        /**       * 短訊服務商提供的KeySecret       */      private String accessKeySecret;        public MsgService(String url, String accessKeyId, String accessKeySecret) {          this.url = url;          this.accessKeyId = accessKeyId;          this.accessKeySecret = accessKeySecret;      }        public int sendMsg(String msg) {          // 調用http服務並發送消息,返回結果          return HttpClientUtils.sendMsg(url, accessKeyId, accessKeySecret, msg);      }        // 省略getter/setter方法  }  

其中MsgService用到了一個工具類HttpClientUtils。在HttpClientUtils中只簡單打印了請求的參數信息。

package com.secbro2.utils;    public class HttpClientUtils {        public static int sendMsg(String url, String accessKeyId, String accessKeySecret, String msg) {          //TODO 調用指定url進行請求的業務邏輯          System.out.println("Http請求,url=" + url + ";accessKeyId=" + accessKeyId + ";accessKeySecret=" + accessKeySecret + ";msg=" + msg);          return 0;      }  }

定義配置類

定義MsgProperties配置類,用於封裝application.properties或application.yml中的基礎配置。這裡關於短訊發送的配置前綴統一採用msg。

@ConfigurationProperties(prefix = "msg")  public class MsgProperties {        /**       * 訪問發送短訊的url地址       */      private String url;        /**       * 短訊服務商提供的請求keyId       */      private String accessKeyId;        /**       * 短訊服務商提供的KeySecret       */      private String accessKeySecret;        // 其他參數定義      // 省略getter/setter方法    }

通過@ConfigurationProperties註解來進行對應的屬性的裝配。

創建自動化配置類

自動配置類就是一個普通的java類,通過不同的註解來對其賦予不同的功能。其中最核心的當然是@Configuration註解。

@Configuration  @ConditionalOnClass(MsgService.class)  @EnableConfigurationProperties(MsgProperties.class)  public class MsgAutoConfiguration {        /**       * 注入屬性配置類       */      @Resource      private MsgProperties msgProperties;        @Bean      @ConditionalOnMissingBean(MsgService.class)      @ConditionalOnProperty(prefix = "msg", value = "enabled", havingValue = "true")      public MsgService msgService() {          MsgService msgService = new MsgService(msgProperties.getUrl(), msgProperties.getAccessKeyId(),                  msgProperties.getAccessKeySecret());          // 如果提供了其他set方法,在此也可以調用對應方法對其進行相應的設置或初始化。          return msgService;      }  }

MsgAutoConfiguration類上的註解,@Configuration用來聲明該類為一個配置類;@ConditionalOnClass註解說明只有當MsgService類存在於classpath中時才會進行相應的實例化;@EnableConfigurationProperties將application.properties中對應的屬性配置設置於MsgProperties對象中;

msgService方法上的註解,@Bean表明該方法實例化的對象會被加載到容器當中;@ConditionalOnMissingBean指明當容器中不存在MsgService的對象時再進行實例化;@ConditionalOnProperty指定了配置文件中msg.enabled=true時才進行相應的實例化。

添加spring.factories

當所有的基礎代碼和自動配置類都準備完成,就需要對其進行註冊。也就是我們熟悉的META-INF/spring.factories配置文件了。當然,這個需要在自己的項目中進行創建。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=  com.secbro2.msg.MsgAutoConfiguration

在spring.factories配置文件中註冊MsgAutoConfiguration類。如果有多個自動配置類,用逗號分隔換行即可。

至此,一個基於Spring Boot的自動配置starter便完成了。使用「maven:install」將其打包到本地maven倉庫或上傳至私服。其他項目便可以通過maven依賴使用。

starter項目使用

在其他項目中,通過以下依賴引入該依賴。

<dependency>      <groupId>com.secbro2</groupId>      <artifactId>spring-boot-starter-msg</artifactId>      <version>1.0-SNAPSHOT</version>  </dependency>

然後在當前項目的application.properties中配置對應的參數:

msg.enabled=true  msg.url=127.0.0.1  msg.accessKeyId=10001  msg.accessKeySecret=afelwjfwfwef

比如其他項目同樣是Spring Boot項目,則可定義一個簡單的Controller來進行測試。

@RestController  public class HelloWorldController {        @Resource      private MsgService msgService;        @RequestMapping("/sendMsg")      public String sendMsg(){          msgService.sendMsg("測試消息");          return "";      }  }

當通過瀏覽器訪問:http://localhost:8080/sendMsg時,便會打印出如下日誌:

Http請求,url=127.0.0.1;accessKeyId=10001;accessKeySecret=afelwjfwfwef;msg=測試消息

說明MsgService對象被自動配置,並且測試通過。

而針對短訊發送這樣的starter,可以進行進一步拓展,實現短訊發送的各種基礎功能,而當其他項目需要時只用引入對應的依賴,並配置具體的參數即可馬上使用,是不是非常方便?

總結下Starter的工作流程:

  • Spring Boot在啟動時掃描項目所依賴的JAR包,尋找包含spring.factories文件的JAR包;
  • 根據spring.factories配置加載AutoConfiguration類;
  • 根據@Conditional註解的條件,進行自動配置並將Bean注入Spring容器。

程序新視界:精彩和成長都不容錯過

程序新視界-微信公眾號