【Spring Boot】16.自定義starter

自定義starter

自定義starter:java

  • 這個場景須要使用到的依賴是什麼?
  • 如何編寫自動配置?

以咱們web場景啓動器的自動配置類WebMVCAutoConfiguration類爲例:web

@Configuration 
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {

在自動配置類中,常常能夠看到以下的註解:spring

  • @Configuration 指明這是一個配置類
  • @ConditionalOnXXX 在指定條件成立的狀況下自動配置類生效
  • @AutoConfigureAfter 指定自動配置類的順序
  • @Bean 給容器中添加組件
  • @ConfigurationPropertie結合相關xxxProperties類來綁定相關的配置
  • @EnableConfigurationPropertiesxxxProperties生效加入到容器中

並且,自動配置類要能加載,須要將他們配置在類路徑下的META-INF/spring.factories.例如springBoot的apache

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\

模式

啓動器只用來作依賴導入,他是一個空jar文件,僅提供輔助性的依賴管理,這些依賴可能用於自動裝配或者其餘類庫。他是專門來寫一個自動配置模塊;啓動器依賴自動配置;別人只須要引入啓動器(starter)就能夠了。springboot

命名規則

  • 官方 spring-boot-starter-模塊名
  • 非官方(如咱們本身編寫的) 模塊名-spring-boot-starter

mybatis-spring-boot-starter;自定義啓動器名-spring-boot-startermybatis

本身作一個starter

建立項目

  1. 新建一個空的項目:hellostarter;
  2. 啓動器(作依賴引入):添加一個module,group_id爲com.zhaoyi.starter,ArtifactId爲hello-spring-boot-stater;
  3. 自動配置(作自動配置):在來添加一個module做爲初始化器,選擇springinitializer建立,group_id爲com.zhaoyi.starter,ArtifactId爲hello-spring-boot-starter-autoconfigurer,不添加任何場景模塊;
  4. 點擊apply,點擊ok。

主程序模塊

啓動器/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.zhaoyi.starter</groupId>
    <artifactId>hello-spring-boot-stater</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.zhaoyi.starter</groupId>
            <artifactId>hello-spring-boot-starter-autoconfigurer</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

其實就是引入另一個自動配置的座標信息便可,至此,啓動器模塊無需加入任何代碼,咱們接下來完善自動配置模塊。app

hello-spring-boot-stater 我這裏starter少寫一個r了,請僞裝他是有r的。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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.zhaoyi.starter</groupId>
    <artifactId>hello-spring-boot-starter-autoconfigurer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hello-spring-boot-starter-autoconfigurer</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

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

</project>

刪除一些其餘沒必要要的依賴,只須要springboot-starer以及spring-boot-configuration-processor,這是全部starer都須要的基本配置。spring-boot

下方的build也記得刪除,由於咱們會刪除主程序的啓動類,插件會報錯。測試

spring-boot-configuration-processor是2.x必須引入的包。

在starter包路徑下添加三個以下類文件

starter/HelloProperties.class

package com.zhaoyi.starter;

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

@ConfigurationProperties(prefix = "zhaoyi.hello")
public class HelloProperties {
    private String prefix;
    private String suffix;

    public String getPrefix() {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public String getSuffix() {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
}

該類配置了Properties類,並強調了與配置文件的zhaoyi.hello前綴的配置關聯,支持prefix以及suffix兩項配置。

starter/HelloService.class

package com.zhaoyi.starter;

public class HelloService {

    private HelloProperties helloProperties;

    public HelloProperties getHelloProperties() {
        return helloProperties;
    }

    public void setHelloProperties(HelloProperties helloProperties) {
        this.helloProperties = helloProperties;
    }

    public String sayHello(String name){
        return helloProperties.getPrefix() + name + helloProperties.getSuffix();
    }
}

該服務類用於對外提供服務,咱們能夠看到他提供了一個方法,用於返回前綴+傳入參數+後綴這樣的字符串,同時提供了一個setter接口,用於HelloServiceAutoConfiguration進行Properties設置。

package com.zhaoyi.starter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnWebApplication
@EnableConfigurationProperties(HelloProperties.class)//屬性文件生效
public class HelloServiceAutoConfiguration {

    @Autowired
    private HelloProperties helloProperties;

    @Bean
    public HelloService helloService(){
        HelloService helloService = new HelloService();
        helloService.setHelloProperties(helloProperties);
        return helloService;
    }
}

該自動配置類和咱們以前查看的springboot的自動配置類的源碼很類似,他使用HelloProperties做爲注入屬性對象,同時往容器中注入一個名爲helloService的bean,提供給用戶消費。

resources/META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.zhaoyi.starter.HelloServiceAutoConfiguration

至此咱們的工做作完了:首先,咱們寫了自動配置類,這個類給容器中給容器中添加HelloService組件,該組件用到的屬性是和HelloProperties綁定的,而HelloProperties的值又是能夠經過從配置文件中進行配置(綁定了前綴zhaoyi.hello),咱們這裏支持兩個屬性即prefix和suffix。最後,咱們經過在resources即類路徑下新建META-INF/spring.factories文件保證springboot啓動後配置類會加載生效。

接下來咱們將整個項目發佈到本地倉庫中(點擊maven install)。先install自動配置模塊,而後在install啓動器模塊(由於啓動器模塊是依賴於自動配置模塊的,所以在後面install)。

咱們會發現,兩個jar包已經被安裝在了咱們的本地倉庫中,接下來,咱們就寫一個測試網站來試試咱們本身的starter吧。

測試

建立一個web項目,選擇web模塊,並在pom文件中引入咱們上一節中本身建立的starter,導入座標信息:

<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.zhaoyi.starter</groupId>
            <artifactId>hello-spring-boot-stater</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

還記得咱們的自定義starter嗎?他提供了兩個配置項,因而,咱們到配置文件中添加此配置。

application.yml

server:
  port: 8085
zhaoyi:
  hello:
    prefix: this is prefix
    suffix: this is suffix

該配置文件指明瞭服務啓動端口8085,同時,設置了咱們自定義場景的配置:prefix以及suffix。好了,萬事俱備,接下來就是消費該場景啓動器提供給咱們的服務了。建立一個controller:

controller/IndexController.class

package com.example.demo.controller;

import com.zhaoyi.starter.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexController {

    @Autowired
    private HelloService helloService;
    
    @RequestMapping("/hello")
    public String index(){
        String hello = helloService.sayHello("hello");
        return hello;
    }
}

在咱們springboot啓動的時候,springboot已經將helloService這個bean注入到了容器中,咱們直接注入到controller中就可使用了,而且咱們配置的值也會隨之裝配到HelloProperties對象上,接下來訪問http://localhost:8085/hello,就能夠獲得如下的輸出:

this is prefixhellothis is suffix

也就在咱們傳入的參數先後分別添加配置的指定值。

至此,咱們的自定義starter完成了,在實際開發中,咱們本身編寫starter的場景其實並很少見,可是你也許會發現不少有趣的事情,若是能把一些經常使用的模塊這樣提取出來,供後來者使用,何嘗不是一種對本身的提高。

相關文章
相關標籤/搜索