需求背景:
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纔會幫你自動配置。
大致思路:
- 查找 spring.factories 中配置加載 AutoConfigure 類
- 根據目標配置類的@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>