1. 程式人生 > 其它 >Spring Boot -- Spring Boot Starter的簡單實現

Spring Boot -- Spring Boot Starter的簡單實現

一、什麼是Spring Boot Starter

1.1 自動裝配

在介紹Spring Boot Starter之前,我們需要了解一下Spring Boot的自動裝配機制,因為Spring Boot Starter的實現依賴於Spring Boot的自動裝配機制。

SpringBoot在程式初始化時可以根據classpath、property屬性、context中例項、以及執行容器特徵等各種動態條件,來按需初始化相應的bean,並註冊到IOC容器中。

SpringBoot啟動的時候通過@EnableAutoConfiguration註解找到META-INF/spring.factories配置檔案中所有的自動配置類,並對其進行載入,而這些自動配置類的類名都是以AutoConfiguration結尾來命名的,它實際上就是一個javaConfig形式的Spring容器配置類,它們都有一個@EnableConfigurationPerperties的註解,通過這個註解啟動XXXProperties命名的類去載入全域性配置中的屬性,如server.port,而XXXProperties通過@ConfigurationProperties註解將全域性配置檔案中的屬性與自己的屬性進行繫結。

1.2 Spring Boot Starter概念

Starter是SpringBoot中的一個非常重要的概念,Starter相當於模組,它能將模組所需的依賴整合起來並對模組內的Bean根據環境(條件)進行自動裝配。使用者只需要依賴相應功能的Starter,無需做過多的配置和依賴,SpringBoot就能自動掃描並載入相應的模組。

Spring Boot Starter它提供了一個自動化配置類,一般命名為 XXXAutoConfiguration ,在這個配置類中通過條件註解來決定一個配置是否生效;然後,它還會提供一系列的預設配置,也允許開發者根據實際情況自定義相關配置;最後,通過型別安全的屬性注入將這些配置屬性注入進來,新注入的屬性會代替掉預設屬性。

例如,如果想使用Spring和JPA訪問資料庫,只需要專案中包含spring-boot-starter-data-jpa 依賴項,就可以正常使用。已有的Spring Boot Starter有很多,常用的有:

  • spring-boot-starter:核心 starter,包括自動化配置支援,日誌以及 YAML
  • spring-boot-starter-test:SpringBoot 測試相關的 starter
  • spring-boot-starter-web:構建 restful、springMVC 的 web應用程式的 starter
  • spring-boot-starter-security:使用 Spring Security 的 starter

二、Spring Boot Starter編寫

2.1 編寫步驟

編寫Starter非常簡單,與編寫一個普通的Spring Boot應用沒有太大區別:

  • 新建Maven專案,在專案的POM檔案中定義使用的依賴;
  • 新建配置類,寫好配置項和預設的配置值,指明配置項字首;
  • 新建自動裝配類,根據 @Conditional註解的條件,使用@Configuration和@Bean來進行自動裝配;
  • 新建spring.factories檔案,指定Starter的自動裝配類;
  • 編寫服務類,也就是我們starter要實現的功能;

2.2 案例

新建maven專案,配置pom檔案:

<?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.5.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.goldwind.example</groupId>
    <artifactId>spring-boot-starter-helloworld</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-starter-helloworld</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.18</version>
        </dependency>

        <!-- 核心 starter,包括自動化配置支援,日誌以及 YAML -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!-- 其中 spring-boot-configuration-processor 的作用是編譯時生成 spring-configuration-metadata.json ,
        此檔案主要給IDE使用。如當配置此jar相關配置屬性在 application.yml ,你可以用ctlr+滑鼠左鍵點選屬性名,IDE會跳轉
        到你配置此屬性的類中。 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <!--  spring boot 測試相關的 starter   -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>
View Code

這裡順帶提一下spring-boot-stater-parent,

spring-boot-starter-parent 主要有如下作用:

  • 定義了 Java 編譯版本。
  • 使用 UTF-8 格式編碼。
  • 繼承自 spring-boot-dependencies,這個裡邊定義了依賴的版本,也正是因為繼承了這個依賴,所以我們在寫依賴時才不需要寫版本號。
  • 執行打包操作的配置。
  • 自動化的資源過濾。
  • 自動化的外掛配置。
  • 針對 application.properties 和 application.yml 的資源過濾,包括通過 profile 定義的不同環境的配置檔案,例如 application-dev.properties 和 application-dev.yml。

新建配置類HelloWorldProperties.java:

package com.goldwind.example;

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

/**
 * 新建配置類,寫好配置項和預設的配置值,指明配置項字首
 *
 * @author zy
 * @since 2021/9/22
 */
@Data
@ConfigurationProperties(prefix = "example")
public class HelloWorldProperties {
    // 姓名
    private String name = "zy";

    // 年齡
    private Integer age = 18;
}

新建自動裝配類HelloWorldAutoConfiguration.java:

package com.goldwind.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
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和@Bean來進行自動裝配
 *
 * @author zy
 * @since 2021/9/22
 */
@Configuration
@ConditionalOnClass(HelloWorldService.class)
@EnableConfigurationProperties(HelloWorldProperties.class)
public class HelloWorldAutoConfiguration {
    @Autowired
    private HelloWorldProperties properties;

    @Bean
    @ConditionalOnMissingBean
    public HelloWorldService starterService() {
        return new HelloWorldService(properties);
    }
}

新建spring.factories(resources/META-INF路徑下):

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.goldwind.example.HelloWorldAutoConfiguration

編寫服務類HelloWorldService.java:

package com.goldwind.example;

/**
 * 編寫服務類,也就是我們starter要實現的功能
 * 輸出配置檔案中的資訊
 *
 * @author zy
 * @since 2021/9/22
 */
public class HelloWorldService {
    private HelloWorldProperties properties;

    /**
     * 建構函式
     */
    public HelloWorldService(HelloWorldProperties properties) {
        this.properties = properties;
    }

    public void helloWorld() {
        System.out.println(String.format("我的名字是%s,我今年%d歲", properties.getName(), properties.getAge()));
    }
}

執行mvn install,生成spring-boot-starter-helloworld.jar。

三、引用Starter

3.1 步驟

  • 將Starter專案的依賴新增到我們自己的spring boot專案中;
  • 在application.yml配置檔案中新增配置資訊;

3.2 案例

新建maven專案,配置pom檔案:

<?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.5.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.goldwind.example</groupId>
    <artifactId>spring-boot-starter-helloworld-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</artifactId>
        </dependency>

        <dependency>
            <groupId>com.goldwind.example</groupId>
            <artifactId>spring-boot-starter-helloworld</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

新建DemoRunner.java:

package com.goldwind.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

/**
 * 通過實現ApplicationRunner或CommandLineRunner介面,可以實現應用程式啟動完成後自動執行run方法
 *
 * @author zy
 * @since 2021/9/22
 */
@Component
public class DemoRunner implements ApplicationRunner {
    @Autowired
    private HelloWorldService helloWorldService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        helloWorldService.helloWorld();
    }
}

新建DemoApplication.java:

package com.goldwind.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

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

修改配置檔案application.yml:

example:
  name: sf
  age: 28

四、原始碼

spring-boot-starter-helloworld

spring-boot-starter-helloworld-demo