【SpringBoot】編寫一個本身的Starter

1、什麼是Starter?

在開發過程當中咱們就常常使用到各類starter,好比mybatis-spring-boot-starter,只須要進行簡單的配置便可使用,就像一個插件很是方便。這也是SpringBoot很是重要的一個特性——自動化配置。php

2、實現

2.1建立一個maven項目並配置pom.xml

命名規範: Spring官方的Starter命名格式通常是spring-boot-starter-{name},好比spring-boot-starter-web 。而非官方的,官方建議artifactId命名應該遵循 {name}-spring-boot-starter的格式,如example-spring-boot-starter。html

pom文件java

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" 
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
  5. <modelVersion>4.0.0</modelVersion> 
  6.  
  7. <groupId>cn.sp</groupId> 
  8. <artifactId>example-spring-boot-starter</artifactId> 
  9. <version>1.0-SNAPSHOT</version> 
  10.  
  11. <properties> 
  12. <spring-boot.version>2.1.5.RELEASE</spring-boot.version> 
  13. </properties> 
  14.  
  15. <dependencies> 
  16. <dependency> 
  17. <groupId>org.springframework.boot</groupId> 
  18. <artifactId>spring-boot-configuration-processor</artifactId> 
  19. <optional>true</optional> 
  20. </dependency> 
  21.  
  22. <dependency> 
  23. <groupId>org.springframework.boot</groupId> 
  24. <artifactId>spring-boot-autoconfigure</artifactId> 
  25. </dependency> 
  26. </dependencies> 
  27.  
  28.  
  29. <dependencyManagement> 
  30. <dependencies> 
  31. <dependency> 
  32. <!-- Import dependency management from Spring Boot --> 
  33. <groupId>org.springframework.boot</groupId> 
  34. <artifactId>spring-boot-dependencies</artifactId> 
  35. <version>${spring-boot.version}</version> 
  36. <type>pom</type> 
  37. <scope>import</scope> 
  38. </dependency> 
  39. </dependencies> 
  40. </dependencyManagement> 
  41.  
  42. </project> 

spring-boot-configuration-processor 的做用是編譯時生成 spring-configuration-metadata.json ,此文件主要給IDE使用,ctlr+鼠標左鍵點擊配置文件(如application.properties)上相關配置屬性,便可跳轉到配置此屬性的類中。git

咱們要實現的一個小功能是讀取配置文件上cn.sp.config的字符串,而後按照給定的分隔符進行分割。github

2.2編寫配置文件讀取類

@ConfigurationProperties(prefix = "cn.sp")
public class StarterServiceProperties {

    private String config;

    public String getConfig() {
        return config;
    }

    public void setConfig(String config) {
        this.config = config;
    }
}

2.3編寫Service

public class StarterService {

    private String config;

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

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

2.4編寫自動配置類(重點)

  1. package cn.sp.autoconfigure; 
  2.  
  3. import org.springframework.beans.factory.annotation.Autowired; 
  4. import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 
  5. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 
  6. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 
  7. import org.springframework.boot.context.properties.EnableConfigurationProperties; 
  8. import org.springframework.context.annotation.Bean; 
  9. import org.springframework.context.annotation.Configuration; 
  10.  
  11. /** 
  12. * Created by 2YSP on 2019/5/22. 
  13. */ 
  14. @Configuration 
  15. @ConditionalOnClass(StarterService.class) 
  16. //@ConditionalOnProperty(prefix = "cn.sp",value = "enable",matchIfMissing = true) 
  17. @EnableConfigurationProperties(StarterServiceProperties.class) 
  18. public class StarterAutoConfigure
  19.  
  20. @Autowired 
  21. private StarterServiceProperties properties; 
  22.  
  23. @Bean 
  24. @ConditionalOnMissingBean 
  25. @ConditionalOnProperty(prefix = "cn.sp",value = "enabled",havingValue = "true"
  26. StarterService starterService()
  27. return new StarterService(properties.getConfig()); 
  28.  
  29.  

說下這幾個註解的做用:web

  1. @ConditionalOnClass:當classpath下發現該類的狀況下進行自動配置。
  2. @EnableConfigurationProperties:使使用 @ConfigurationProperties 註解的類生效。具體能夠參考https://www.jianshu.com/p/7f54da1cb2eb
  3. @ConditionalOnMissingBean:當Spring上下文中不存在該Bean時生效。
  4. @ConditionalOnProperty(prefix = "cn.sp",value = "enabled",havingValue = "true"),當配置文件中cn.sp.enabled=true時有效。

下面列舉SpringBoot中的全部@Conditional註解及做用spring

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

2.5建立spring.factories

resources/META-INF/ 文件夾下建立spring.factories文件,內容以下:json

org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.sp.autoconfigure.StarterAutoConfigurebash

右邊的就是自動配置類的類路徑,注意單詞別打錯了,我就是META-INF打成了MATA-INF害我折騰了半天。

3、測試

  1. 執行mvn install命令打包到本地
  2. 在另一個項目添加依賴
<dependency>
            <groupId>cn.sp</groupId>
            <artifactId>example-spring-boot-starter</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

而後能夠看到jar包的結構圖以下:
enter description here
3. 在application.properties文件添加以下內容

cn.sp.enabled=true
cn.sp.config=fdafdf,ss1,DSDS,DDD
  1. 編寫測試類並啓動
@RunWith(SpringRunner.class)
@SpringBootTest
public class MySpringbootApplicationTests {


    @Autowired
    StarterService starterService;

    @Test
    public void contextLoads() {
        String[] strings = starterService.split(",");
        for (int i = 0; i < strings.length; i++) {
            System.out.println(strings[i]);
        }
    }

}
  1. 運行結果以下則表示成功。

2019-05-23 10:41:49.219 [main] INFO cn.sp.MySpringbootApplicationTests - Started MySpringbootApplicationTests in 10.977 seconds (JVM running for 13.035)
fdafdf
ss1
DSDS
DDD

2019-05-23 10:41:52.411 [Thread-4] INFO o.s.w.c.s.GenericWebApplicationContext - Closing org.springframework.web.context.support.GenericWebApplicationContext@51f49060: startup date [Thu May 23 10:41:38 CST 2019]; root of context hierarchy

4、原理

1.在應用程序啓動過程當中,Spring Boot使用SpringFactoriesLoader類加載器查找org.springframework.boot.autoconfigure.EnableAutoConfiguration關鍵字對應的Java配置文件。Spring Boot會遍歷在各個jar包中META-INF目錄下的spring.factories文件,構建成一個配置文件鏈表。
2.根據spring.factories配置加載AutoConfigure類
3.根據 @Conditional註解的條件,進行自動配置並將Bean注入Spring Context中。
注意: Spring Boot的starter在編譯時不須要依賴Spring Boot的庫。
代碼地址:https://github.com/2YSP/example-spring-boot-starter
參考:
https://juejin.im/entry/58d37630570c350058c2c15c
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html

相關文章
相關標籤/搜索