編寫本身的SpringBoot-starter

前言

咱們都知道可使用SpringBoot快速的開發基於Spring框架的項目。因爲圍繞SpringBoot存在不少開箱即用的Starter依賴,使得咱們在開發業務代碼時可以很是方便的、不須要過多關注框架的配置,而只須要關注業務便可。java

例如我想要在SpringBoot項目中集成Redis,那麼我只須要加入spring-data-redis-starter的依賴,並簡單配置一下鏈接信息以及Jedis鏈接池配置就能夠。這爲咱們省去了以前不少的配置操做。甚至有些功能的開啓只須要在啓動類或配置類上增長一個註解便可完成。web

那麼若是咱們想要本身實現本身的Starter須要作些什麼呢?下面就開始介紹如何實現本身的SpringBoot-xxx-starter。redis

原理

首先說說原理,咱們知道使用一個公用的starter的時候,只須要將相應的依賴添加的Maven的配置文件當中便可,免去了本身須要引用不少依賴類,而且SpringBoot會自動進行類的自動配置。那麼 SpringBoot 是如何知道要實例化哪些類,並進行自動配置的呢? 下面簡單說一下。spring

首先,SpringBoot 在啓動時會去依賴的starter包中尋找 resources/META-INF/spring.factories 文件,而後根據文件中配置的Jar包去掃描項目所依賴的Jar包,這相似於 Java 的 SPI 機制。json

第二步,根據 spring.factories配置加載AutoConfigure類。springboot

最後,根據 @Conditional註解的條件,進行自動配置並將Bean注入Spring Context 上下文當中。app

咱們也可使用@ImportAutoConfiguration({MyServiceAutoConfiguration.class}) 指定自動配置哪些類。框架

實現

終於到了代碼實現的步驟,接下來就開始編碼咱們本身的SpringBoot-starter。spring-boot

第一步建立一個SpringBoot 項目,並添加下面兩個依賴到pom.xml文件當中

<dependencies>
    <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>
</dependencies>

其中 spring-boot-configuration-processor 的做用是編譯時生成 spring-configuration-metadata.json ,此文件主要給IDE使用。如當配置此jar相關配置屬性在 application.yml ,你能夠用ctlr+鼠標左鍵點擊屬性名,IDE會跳轉到你配置此屬性的類中。測試

咱們平常使用的Spring官方的Starter通常採起spring-boot-starter-{name} 的命名方式,如 spring-boot-starter-web 

而非官方的Starter,官方建議 artifactId 命名應遵循{name}-spring-boot-starter 的格式。 例如:ysc-spring-boot-starter 

<groupId>com.ysc</groupId>
<artifactId>simple-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>

第二步編寫咱們的Service類

這裏講一下咱們的Starter要實現的功能,很簡單,提供一個Service,包含一個可以將配置文件中配置的字符串根據傳入的字符進行分割的方法String[] split(String separatorChar)

public class StarterService {
    private String config;

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

第三步編寫配置文件讀取類

@ConfigurationProperties("example.service")
public class StarterServiceProperties {
    private String config;
    
    public void setConfig(String config) {
        this.config = config;
    }
    
    public String getConfig() {
        return config;
    }
 }

第四步,編寫AutoConfigure類 ,這步是關鍵點

@Configuration
@ConditionalOnClass(StarterService.class)
@EnableConfigurationProperties(StarterServiceProperties.class)
public class StarterAutoConfigure {

    @Autowired
    private StarterServiceProperties properties;

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "example.service", value = "enabled", havingValue = "true")
    StarterService starterService (){
        return new StarterService(properties.getConfig());
    }

}

解釋一下代碼中用到的幾個註解:

  • @ConditionalOnClass,當classpath下發現該類的狀況下進行自動配置。
  • @ConditionalOnMissingBean,當Spring Context中不存在該Bean時。
  • @ConditionalOnProperty(prefix = "example.service",value = "enabled",havingValue = "true"),當配置文件中example.service.enabled=true時。
下面列舉SpringBoot中的全部@Conditional註解及做用
@ConditionalOnBean:當容器中有指定的Bean的條件下  
@ConditionalOnClass:當類路徑下有指定的類的條件下  
@ConditionalOnExpression:基於SpEL表達式做爲判斷條件  
@ConditionalOnJava:基於JVM版本做爲判斷條件  
@ConditionalOnJndi:在JNDI存在的條件下查找指定的位置  
@ConditionalOnMissingBean:當容器中沒有指定Bean的狀況下  
@ConditionalOnMissingClass:當類路徑下沒有指定的類的條件下  
@ConditionalOnNotWebApplication:當前項目不是Web項目的條件下  
@ConditionalOnProperty:指定的屬性是否有指定的值  
@ConditionalOnResource:類路徑下是否有指定的資源  
@ConditionalOnSingleCandidate:當指定的Bean在容器中只有一個,或者在有多個Bean的狀況下,用來指定首選的Bean @ConditionalOnWebApplication:當前項目是Web項目的條件下

最後一步,在resources/META-INF/下建立spring.factories文件,並添加以下內容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.autocinfigure.StarterAutoConfigure

至此,咱們的一個Starter代碼部分就是完成了,下面將項目安裝到本地Maven倉庫中。

發佈

在項目根目錄執行 mvn install 進行打包安裝。

測試

將Starter項目的依賴添加到咱們本身的SpringBoot項目中

<dependency>
    <groupId>com.ysc</groupId>
    <artifactId>simple-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
 </dependency>

application.yml 配置文件中添加配置信息:

example
  service
    enabled: true
    config: abc-des-dde,SSS-DRS-RE,SDR-SDFR-XXX

在本地使用JUnit進行代碼測試

@Autowired
private StarterService starterService;

@Test
public void starterTest() {
    String[] splitArray = starterService.split(",");
    System.out.println(splitArray);
}

好,到這咱們的一個自定義Stater就完成了
img

相關文章
相關標籤/搜索