1. 程式人生 > 其它 >SpringBoot自定義starter操作

SpringBoot自定義starter操作

自定義Starter

1.Starter介紹    

Starter場景啟動器是Spring Boot中一種非常重要的機制,它將繁瑣的配置統一整合到stater中,我們只需要通過在Maven將starter的依賴匯入專案,SpringBoot 就能自動掃描並載入相應的預設配置。starter的出現簡化了開發人員的工作量,從繁瑣的框架配置中解救出來,讓更多的時間專注在業務邏輯的開發,提高了開發效率。

2.命名規範    

SpringBoot 提供的 starter 以 spring-boot-starter-xxx 的形式命名。為了與 SpringBoot 生態提供的 starter 進行區分,官方建議第三方開發者或技術(例如 Druid、Mybatis 等等)廠商自定義的 starter 使用 xxx-spring-boot-starter 的形式命名,例如 mybatis-spring-boot-starter、druid-spring-boot-starter 等等。

3.模組規範    

Spring Boot 官方建議我們在自定義 starter 時,建立兩個 Module :autoConfigure Module(SpringBoot模組) 和 starter Module(Maven 模組),其中 starter Module 依賴於 autoConfigure Module。當然,這只是 Spring Boot 官方的建議,並不是硬性規定,若不需要自動配置程式碼和依賴專案分離,我們也可以將它們組合到同一個 Module 裡。

4.自定義Starter

1)starter啟動原理

  • starter-pom引入 autoconfigure 包
  • autoconfigure包中配置使用 META-INF/spring.factoriesEnableAutoConfiguration 的值,使得專案啟動載入指定的自動配置類

 

  • 編寫自動配置類 xxxAutoConfiguration -> xxxxProperties
    • @Configuration  //配置類

    • @ConditionalOnMissingBean   //條件裝配

    • @EnableConfigurationProperties(xxxProperties.class)  //開啟屬性繫結功能(在配置檔案中修改值)+將繫結類xxxProperties加入容器

    • @Bean //生成元件

    • ......             

引入starter --- xxxAutoConfiguration --- 容器中放入元件 ---- 繫結xxxProperties ---- 配置項修改

5.自定義starter具體實操

(1)建立一個名為 spring-boot-customer-starter  空工程,工程下面新建兩個模組

 

 

 

 

 

 

 

1)hello-spring-boot-starter(場景啟動器,普通Maven工程);

 

 

 

2)hello-spring-boot-starter-autoconfigure(自動配置包,需用用到Spring Initializr建立的Maven工程);

 

 

 

 

 

 

 

 

 

 

 3)hello-spring-boot-starter無需編寫什麼程式碼,只需讓該工程引入hello-spring-boot-starter-autoconfigure依賴

 hello-spring-boot-starter 的 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.liang</groupId>
    <artifactId>hello-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>

<!--引入 hello-spring-boot-starter-autoconfigure 依賴 --> <dependencies> <dependency> <groupId>com.liang</groupId> <artifactId>hello-spring-boot-starter-autoconfigure</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project>

 

hello-spring-boot-starter-autoconfigure的 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 https://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.6.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.liang</groupId>
    <artifactId>hello-spring-boot-starter-autoconfigure</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hello-spring-boot-starter-autoconfigure</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>
    </dependencies>
</project>

 

(2)建立hello-spring-boot-starter-autoconfigure中的整個目錄

 

 (3)定義Properties類

在com.liang.hello.bean包下建立一個實體類:HelloProperties,通過它來對映配置資訊。

package com.liang.hello.bean;

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

/**
 * @ConfigurationProperties("hello")是springboot提供讀取配置檔案的一個註解
 *  1)讓當前類的屬性和配置檔案中以 hello開頭的配置進行繫結
 *  2)以 hello為字首在配置檔案中讀取/修改當前類中的屬性值
 */
@ConfigurationProperties("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;
    }
}

 

(4)定義Service類

在com.liang.hello.service包下建立一個HelloService類:實現具體業務功能。

package com.liang.hello.service;

import com.liang.hello.bean.HelloProperties;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 預設不要放在容器中
 */
public class HelloService {

    /**
     * @Autowired:自動注入屬性
     * 在bean中的屬性上通過@Autowired實現自定義bean型別的屬性注入
     * 使用是對應的bean必須被spring管理,即手動配置了bean或者在類上添加了@Component註解
     *   DI:就是注入功能,通俗的說就是給IOC創建出來的物件屬性賦值
     */
    @Autowired
    private HelloProperties helloProperties;

    //sayHello(String userName)方法
    public String sayHello(String userName)
    {
        return helloProperties.getPrefix()+": "+userName+">> "+helloProperties.getSuffix();
    }
}

 

(5)定義自動配置類

在com.liang.hello.autoConfig包下建立一個HelloAutoConfiguration配置類。

package com.liang.hello.autoConfig;

import com.liang.hello.bean.HelloProperties;
import com.liang.hello.service.HelloService;
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;

@Configuration //標識配置類
@EnableConfigurationProperties(HelloProperties.class)//開啟屬性繫結功能+預設將HelloProperties放在容器中
public class HelloAutoConfiguration {

    /**
     * @Bean註解用於告訴方法,產生一個Bean物件,然後這個Bean物件交給Spring管理。
     * 產生這個Bean物件的方法Spring只會呼叫一次,隨後這個Spring將會將這個Bean物件放在自己的IOC容器中;
     *
     * @ConditionalOnMissingBean(HelloService.class)
     * 條件裝配:容器中沒有HelloService這個類時標註的方法才生效 / 建立一個HelloService類
     */
    @Bean
    @ConditionalOnMissingBean(HelloService.class)
    public HelloService helloService()
    {
        HelloService helloService = new HelloService();
        return helloService;
    }
}

 

(6)建立spring.factories檔案

1)Spring Factories機制是Spring Boot中一種服務發現機制,這種機制與Java SPI類似。

2)Spring Boot會自動掃描所有Jat包類路徑下META-INF/spring.factories檔案,並讀取其中的內容,進行例項化。這種機制也是Spring Boot Starter的基礎。

3)在helllo-spring-boot-starter-autoconfigure 的類路徑下(resources )中建立一個 META-INF 資料夾,並在 META-INF 資料夾中建立一個 spring.factories 檔案,並新增如下配置

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.liang.hello.autoConfig.HelloAutoConfiguration

4)注意:在spring.factories中顯示指定這些配置類的目錄,注意“,”後不要有空格之類的符號,就只寫該類的全路徑,不然會出現無法找到此bean的錯誤。

 

(7)構建starter

利用maven外掛將兩個工程打包到本地倉庫中。

1)自定義的本地倉庫目錄

 

 

 

2)將寫好的專案打包到本地倉庫中

 

 

  

                                                    最後自定義的starter構建成功!

 

總結使用引入starter --- xxxAutoConfiguration --- 容器中放入元件 ---- 繫結xxxProperties ---- 配置項修改

總結自定義

a.建立一個空工程,在裡面建立xxx-spring-boot-starter工程+建立 xxx-spring-boot-starter-autoConfigure工程;

b.在xxx-spring-boot-starter工程中引入xxx-spring-boot-starter-autoConfigure工程的依賴;

c.建立xxxAutoConfiguration,開啟自動屬性繫結功能(繫結xxxProperties),裡面新增需要元件;

d.在 xxx-spring-boot-starter-autoConfigure工程的 resources 包下建立META-INF/spring.factories檔案,裡面加入自動配置類的類路徑;

e.分別對兩個工程進行clean+install操作,將自定義的starter編譯並打包到本地倉庫,注意時刻保持最新狀態。


 

補充:maven的install可以將專案本身編譯並打包到本地倉庫,這樣其他專案引用本專案的jar包時不用去私服上下載jar包,直接從本地就可以拿到剛剛編譯打包好的專案的jar包,很靈活,避免每次都需要重新往私服釋出jar包的痛苦。

 


 

6、建立一個測試專案,引入自定義的starter依賴使用

(1)用Spring Initializr建立名為hello-spring-boot-starter-test工程,引入hello-spring-boot-starter依賴+spring web依賴測試

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

 

(2)建立配置檔案application.yaml,修改相應的屬性配置項

 

 (3)定義Controller

在com.liang.hello.controller包下建立一個HelloController類:

package com.liang.hello.controller;

import com.liang.hello.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController //=@Controller+@ResponseBody
public class HelloController {

    @Autowired
    HelloService helloService;

    @GetMapping("/hello") //處理get請求方式的/hello請求路徑
    public String sayHello()   //處理方法
    {
        String s = helloService.sayHello("阿嬌");
        return s;
    }
}

 

(4)執行

 

 

 執行成功!自定義starter有效。