SpringBoot魔法堂:說說帶智能提示的spring-boot-starter


前言

前幾個月和隔壁組的老王閑聊,他說項目的供應商離職率居高不下,最近還有開發剛接手ESB訂閱發布接口才兩周就提出離職,而他能做的就只有苦笑和默默地接過這個爛攤子了。
而然幸福的家庭總是相似的,而不幸的我卻因業務變革走上了和老王一樣的道路。單單是接口的開發居然能迫使一位開發毅然決然地離職,我既不相信是人性的扭曲,更不信是道德的淪喪。
拋開這個富有色彩的故事而言,我發現原來的項目存在如下問題:

  1. 沒有使用任何現代依賴管理和構建工具(如Maven, Gradle),直接把所依賴的Jar包存放在項目目錄下的lib目錄中,日積月累導致lib目錄下存放大量無用Jar包;
  2. 沒有使用代碼版本管理工具管理代碼;
  3. 技術文檔欠缺,全靠師傅帶徒弟的方式傳授框架使用方式和開發流程;
  4. 機械性配置項多,而后來的開發人員大多只能依葫蘆畫瓢添加配置,既容易出錯同時又增加問題排查的難度。
    針對前兩個問題,我們只需梳理出必須的依賴項並加入Maven或Gradle管理,然后托管到Git即可。
    而后兩者則可以通過spring-boot-starter將必選依賴項和配置統一管理,並附上相關技術文檔;然后通過模板模式和注解簡化開發流程,提供Demo降低入門難度。
    最后就可以把具體的業務功能開發交給供應商處理,我們專心做好過程管理和驗收即可。

本文將着重分享spring-boot-starter開發的事項,請坐好扶穩!

命名規范

在自定義starter前我們總要思考如何命名我們的starter,而官方提供如下的命名規范:

  1. 官方的starter以spring-boot-starter作為前綴命名項目
    如:spring-boot-starter-web
  2. 非官方的則以spring-boot-starter作為后綴命名項目
    如:mybatis-spring-boot-starter

項目結構

通過Spring Initializr或Spring Boot CLI創建項目結構后,將pom.xml的相關項目修改為如下內容

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifacId>
  <version>2.3.1.RELEASE</version>
  <relativePath/>
</parent>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>

  <!-- 下面為自定義Starter的依賴項 -->
</dependencies>

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
	<source>1.8</source>
	<target>1.8</target>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-source-plugin</artifactId>
      <version>2.4</version>
      <executions>
	<execution>
	  <goals>
	    <goal>jar</goal>
	  </goals>
	</execution>
      </executions>
    </plugin>
  </plugins>
</build>

在starter中我們會定義SpringBean的注冊配置和屬性配置,如ESB訂閱服務的配置項目為

@Configuration
@EnableConfigurationProperties({EsbServerProperties.class})
public class EsbServerConfiguration {
    @Bean
    public SpringBus springBus(){
        return new SpringBus();
    }

    @Bean
    public LoggingFeature loggingFeature(){
        return new LoggingFeature();
    }

    @Bean
    public List<JMSConfigFeature> jmsConfigFeatures(EsbServerProperties props) throws JMSException {
        List<JMSConfigFeature> features = new ArrayList<>();
          
        /** 
         * 這里會使用EsbServerProperties的屬性構建Bean實例
         */

        return features;
    }
}

屬性配置項

// 從application.yml等配置文件中讀取並綁定esb.server.destination等屬性值
@Data
@ConfigurationProperties("esb.server")
public class EsbServerProperties {
    String destination;
    int currConsumers = 1;
    String channel;
    int ccsid = 1205;
    int transportType = 1;
    List<String> connectionNameLists;
    boolean replyError = false;
    String replySuccessText = "Success";
    String replyErrorText = "Failure";
}

到這里我們已經完成一個基本的starter的功能

  1. 通過@ConfigurationProperties定義該starter注冊bean時需要的屬性集合
  2. 通過@Configuration定義該starter注冊的bean

但引用該starter的項目要如何啟用配置呢?其實有兩種方式,分別為手動和自動,其中我們會着重講解自動啟用配置。

手動啟用配置

所謂手動啟用配置其實就是在SpringBoot入口類上添加啟用配置用的自定義注解,針對上面的EsbServerConfiguration我們可以自定義EnableESBSrv注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({EsbServerConfiguration.class})
public @interface EnableEsbSrv {
}

然后入口類的@SpringBootApplication注解前后添加@EnableEsbSrv即可。

讓人省心省力的自動啟用配置

自動啟用配置即只需在pom.xml中引入所依賴的starter,然后啟用應用即可自動啟用該starter的@Configuration所注解的類從而注冊Bean和讀取屬性配置。
而這一切都是由AutoConfigurationImportSelector來操刀,而我們可以通過@EnableAutoConfiguration@SpringBootApplication等實例化AutoConfigurationImportSelector類,配合菜譜resources/META-INF/spring.factories實現自動化配置的功能。
具體手法就是:將EsbServerConfiguration的全限類名稱寫在resources/META-INF/spring.factories的org.springframework.boot.autoconfigure.EnableAutoConfiguration下, 若存在多個則用逗號分隔。

org.springframework.boot.autoconfigure.EnableAutoConfiguration = \
com.john.starter.EsbServerConfiguration,\
com.john.starter.OtherConfiguration

好與更好——集成IDE智能提示

應用啟動時會將application.yml中對應的配置項綁定到@ConfigurationProperties標注的類實例上,那么對於應用開發人員而言日常工作就是修改application.yml的配置項。但IDE又缺少配置項的智能提示,那就很低效了。幸虧Spring Boot早就為我們提供好解決方案,分為手工和自動兩種。為了效率當然是可以自動就不用手動的了。

Starter項目的工作

  1. 引入spring-boot-configuration-processor依賴項;
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-configuration-processor</artifactId>
  <optional>true</optional>
</dependency>
  1. 若src/resources/META-INF/spring-configuration-metadata.json不存在,那么執行mvn compile時會生成target/classes/META-INF/spring-configuration-metadata.json;
  2. 復制target/classes/META-INF/spring-configuration-metadata.json到src/resources/META-INF/spring-configuration-metadata.json即可。

業務系統項目的工作

  1. 引入spring-boot-configuration-processor依賴項;
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-configuration-processor</artifactId>
  <optional>true</optional>
</dependency>
  1. IDEA安裝Spring Assistant插件,並啟用Enable annotation processing(勾選 Settings/Build, Execution & Deployment/Compiles/Annotation Processors/Enable annotation processing)。

總結

spring-boot-starter非常適合用於團隊的技術積累和沉淀,不過想恰到好處地應用起來,不僅要需要深入Spring內部原理還要梳理清楚業務邏輯。后續我們再深入探討Spring內核的事情吧!

轉載請注明來自:https://www.cnblogs.com/fsjohnhuang/p/13956039.html —— ^_^肥仔John


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM