1. 程式人生 > >springboot--自定義starter

springboot--自定義starter

轉載:https://www.jianshu.com/p/45538b44e04e

眾所周知(不知道?點此),Spring Boot由眾多Starter組成,隨著版本的推移Starter家族成員也與日俱增。在傳統Maven專案中通常將一些層、元件拆分為模組來管理,以便相互依賴複用,在Spring Boot專案中我們則可以建立自定義Spring Boot Starter來達成該目的。

好,開始,先建立一個Maven專案並引入依賴,pom.xml如下,供參考~

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>example-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <!-- Import dependency management from Spring Boot -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>1.5.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

這裡說下artifactId的命名問題,Spring 官方 Starter通常命名為spring-boot-starter-{name}spring-boot-starter-webSpring官方建議非官方Starter命名應遵循{name}-spring-boot-starter的格式。

這裡講一下我們的Starter要實現的功能,很簡單,提供一個Service,包含一個能夠將字串加上前後綴的方法String wrap(String word)

public class ExampleService {

    private String prefix;
    private String suffix;

    public ExampleService(String prefix, String suffix) {
        this.prefix = prefix;
        this.suffix = suffix;
    }
    public String wrap(String word) {
        return prefix + word + suffix;
    }
}

字首、字尾通過讀取application.properties(yml)內的引數獲得

@ConfigurationProperties("example.service")
public class ExampleServiceProperties {
    private String prefix;
    private String suffix;
    //省略 getter setter

重點,編寫AutoConfigure

@Configuration
@ConditionalOnClass(ExampleService.class)
@EnableConfigurationProperties(ExampleServiceProperties.class)
public class ExampleAutoConfigure {

    @Autowired
    private ExampleServiceProperties properties;

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "example.service",value = "enabled",havingValue = "true")
    ExampleService exampleService (){
        return  new ExampleService(properties.getPrefix(),properties.getSuffix());
    }

}

解釋下用到的幾個和Starter相關的註解:

  • @ConditionalOnClass,當classpath下發現該類的情況下進行自動配置。
  • @ConditionalOnMissingBean,當Spring Context中不存在該Bean時。
  • @ConditionalOnProperty(prefix = "example.service",value = "enabled",havingValue = "true"),當配置檔案中example.service.enabled=true時。

更多相關注解,建議閱讀官方文件該部分

最後一步,在resources/META-INF/下建立spring.factories檔案,內容供參考下面~

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

OK,完事,執行 mvn:install打包安裝,一個Spring Boot Starter便開發完成了。如果你需要該Starter的原始碼,點這裡


建立一個Spring Boot專案來 試試~

引入example-spring-boot-starter依賴

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

建立application.properties,進行配置

example.service.enabled=true
example.service.prefix=####
[email protected]@@@

建立一個簡單的Spring Web Application,注入Starter提供的ExampleService看它能否正常工作~

@SpringBootApplication
@RestController
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Autowired
    private ExampleService exampleService;

    @GetMapping("/input")
    public String input(String word){
        return exampleService.wrap(word);
    }

}

啟動Application,訪問/input介面試試看~


總結下Starter的工作原理

  1. Spring Boot在啟動時掃描專案所依賴的JAR包,尋找包含spring.factories檔案的JAR包
  2. 根據spring.factories配置載入AutoConfigure
  3. 根據 @Conditional註解的條件,進行自動配置並將Bean注入Spring Context