編寫自定義spring-boot-starter

需求背景:

       Springboot是Spring旗下優秀的子項目之一,其核心理念之一:約定優於配置。通過自動化的配置極大的提升了我們的開發效率,目前已集成諸多組件的starter起步依賴,幫助我們更加快速的構建標準化的應用。

      starter作爲springboot的一大特色,作爲自動配置的核心組成,包括的優點如下:

  • 快速創建獨立運行的Spring項目以及與主流框架集成
  • 使用嵌入式的Servlet容器,應用無需打成WAR包
  • starters自動依賴與版本控制
  • 大量的自動配置,簡化開發,也可修改默認值
  • 無需配置XML,無代碼生成,開箱即用
  • 準生產環境的運行時應用監控
  • 與雲計算的天然集成

Springboot支持自定義的starter,在開發過程中,我們若有一系列初始化配置需要在spring容器啓動時完成初始化,此時我們可以把這批操作封裝爲一個starter,在目標項目中通過maven座標引入。starter依賴於宿主項目的spring上下文環境,與我們傳統方式在spring項目中注入bean不同,它本身可以獨立開發,並打包引入到spring應用中。

以下以自動配置類作爲案例。

原理

       在springboot應用開發中,當我們在pom文件中引入starter組件依賴座標時,啓動Spring容器,此時應用會去依賴的Starter包中查找resources/META-INF/spring.factories文件,根據文件中配置去加載相應的自動配置類,類似於Java的SPI機制。簡單的說自動配置是根據約定來的,也就是說springboot要求必須按照他給的規則開發starter纔會幫你自動配置。

大致思路:

  1. 查找 spring.factories 中配置加載 AutoConfigure 類
  2. 根據目標配置類的@Condition註解條件,將相應的配置bean注入到當前spring Context上下文環境中。也可以通過@EnableConfigurationProperties將指定配置類加載進來

代碼實現

1.編寫自己的starter,建立springboot項目,應用名demo-springboot-starter,添加maven座標如下:

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

2.編寫Service

主要實現該Starter主要實現的業務邏輯,這裏是將配置文件中的配置加載進來,然後根據特定符號進行分割

package cn.jyycode.service;

import org.springframework.util.StringUtils;

/**
 * 編寫配置業務類
 *
 * @author [email protected]
 * @version 1.0.0
 * @date 2019/5/22 10:34
 */
public class StarterService {

    private String config;

    public StarterService(String config) {
        this.config = config;
    }

    public String[] split(String separatorChar) {
        return StringUtils.split(this.config, separatorChar);
    }
}

3.配置文件讀取類

package cn.jyycode.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * 配置文件讀取類
 *
 * @author [email protected]
 * @version 1.0.0
 * @date 2019/5/22 10:38
 */
@ConfigurationProperties("cn.jyycode.service")
@Data
public class StarterServiceProperties {

    private String config;
}

4.編寫AutoConfigure類,這是starter啓動時加載spring.factories指定的啓動配置類

package cn.jyycode.config;

import cn.jyycode.service.StarterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Starter啓動自動配置類
 *
 * @author [email protected]
 * @version 1.0.0
 * @date 2019/5/22 10:43
 */
@Configuration
@ConditionalOnClass(StarterService.class)
@EnableConfigurationProperties(StarterServiceProperties.class)
public class StarterAutoConfigure {

    @Autowired
    private StarterServiceProperties properties;

    @Bean
    @ConditionalOnMissingBean(StarterService.class)
    public StarterService starterService(){
        System.out.println("demo-spring-boot-starter run success:"+properties.getConfig());
        return new StarterService(properties.getConfig());
    }
}

本類中使用了@Conditional註解,它是Spring4提供的一個新特性,用於根據特定條件來控制bean的創建行爲。主要包括:

@ConditionalOnBean:當容器中有指定的Bean的條件下  
@ConditionalOnClass:當類路徑下有指定的類的條件下  
@ConditionalOnExpression:基於SpEL表達式作爲判斷條件  
@ConditionalOnJava:基於JVM版本作爲判斷條件  
@ConditionalOnJndi:在JNDI存在的條件下查找指定的位置  
@ConditionalOnMissingBean:當容器中沒有指定Bean的情況下  
@ConditionalOnMissingClass:當類路徑下沒有指定的類的條件下  
@ConditionalOnNotWebApplication:當前項目不是Web項目的條件下  
@ConditionalOnProperty:指定的屬性是否有指定的值  
@ConditionalOnResource:類路徑下是否有指定的資源  
@ConditionalOnSingleCandidate:當指定的Bean在容器中只有一個,或者在有多個Bean的情況下,用來指定首選的Bean 
@ConditionalOnWebApplication:當前項目是Web項目的條件下  

5.在resources/META-INF/下創建spring.factoris文件,添加內容:(factories文件爲k-v格式,v可以有多個,用 \ 號分隔,v值根據自己的實際配置類路徑)

org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.jyycode.config.StarterAutoConfigure

6.打包發佈自己的Starter

在idea或當前項目根目錄下打開終端,執行mvn clean install -U,將項目打包並安裝到本地maven倉庫中去

7.新建新項目demo

引入demo-springboot-starter座標依賴

<dependency>
     <groupId>cn.jyycode</groupId>
     <artifactId>demo-spring-boot-starter</artifactId>
     <version>0.0.1-SNAPSHOT</version>
</dependency>

8.啓動項目

可以看到,demo-springboot-starter隨着項目啓動,並完成了配置的自動化裝載。

運行結果:

9.有個小坑

在starter項目進行maven打包時,注意在pom中插件添加如下配置:configuration.skip=true。否則在打包時會在class目錄下生成BOOT-INF文件夾,導致spring.factories中配置的類無法找到,導致整個spring應用啓動失敗。

<plugins>
    <plugin>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-maven-plugin</artifactId>
       <configuration>
           <skip>true</skip>
       </configuration>
     </plugin>
</plugins>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章