面試官:小夥子,說一下「SpringBoot」 Starter 該怎麼寫吧

1 前言

從前從前,有個面試官問我一個 SpringBoot Starter 的開發流程,我說我沒有寫過 starter,然後就沒有然後了,面試官說我技術深度不夠。

我想說這東西不是很簡單嗎,如果要自己寫一個出來也是分分鐘的事情。至於就因爲我沒有寫過 starter 就覺得我一點都不會 SpringBoot 嗎?

當然我當時確實水平不足,連 Java 的 SPI 都忘了是啥,後來又撿了起來,原來我在大學的時候就用過 Java 的 SPI,悔之晚矣!

2 什麼是 SpringBoot starter

starter 是 SpringBoot 的一個重要的組成部分,它相當於一個集成的模塊,比如你想用 Mybatis 和 lombok,但是在 pom 文件中需要寫兩個依賴,如果你將它們集成爲一個 starter(或者將更多你需要的依賴集成進去),那麼你只需要在 pom 文件中寫一個 starter 依賴就可以了,這對於一個可複用模塊的開發和維護都極爲有利。

同時,在 maven 中引入 starter 依賴之後,SpringBoot 就能自動掃描到要加載的信息並啓動相應的默認配置,它遵循“約定大於配置”的理念。

3 如何開發一個 SpringBoot starter

3.0 環境說明

jdk 1.8.0_151

maven 3.6.3

IDEA 編譯器

要開發的 starter 是一個日期格式化工具,它的功能是可以指定如何格式轉化日期類型,同時在配置文件中可以開啓關閉此功能

3.1 創建項目

在 IDEA 中新建一個 maven 工程,如下圖所示。

面試官:小夥子,說一下「SpringBoot」 Starter 該怎麼寫吧

 

Spring 官方建議自定義的 starter 使用 xxx-spring-boot-starter 命名規則,以區分 SpringBoot 生態提供的 starter。

然後需要在 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>
    <groupId>org.walker.planes</groupId>
    <artifactId>date-format-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.3.0.RELEASE</version>
        </dependency>
    </dependencies>
</project>

3.2 創建配置信息實體類

在開發 SpringBoot 項目的時候,我們有時候會在 application.properties 配置文件中進行一些配置的修改,用以開啓或修改相關的配置,如 server.port 可以用來修改項目啓動的端口,所以在編寫自定義日期格式化 starter 時,也可以用到這個功能,根據配置文件來開啓或關閉某項功能。

我們在 application.properties 配置文件中新增兩個配置項,第一個是用來控制該 starter 的啓動或關閉,第二個是需要指定的格式化信息。

然後創建一個配置文件映射類,它的私有成員變量 pattern 就是需要在配置文件中指定的屬性,如果沒有指定默認值爲 yyyy-MM-dd HH:mm:ss。

import org.springframework.boot.context.properties.ConfigurationProperties;
/**
 * 配置信息實體類
 * @author Planeswalker23
 * @date 2020-05-25
 */
@ConfigurationProperties("formatter")
public class DateFormatProperties {
    /**
     * default format pattern
     */
    private String pattern = "yyyy-MM-dd HH:mm:ss";
    // 忽略 getter setter
}

@ConfigurationProperties(prefix = “formatter”) 註解的作用是將相同前綴的配置信息通過配置項名稱映射成實體類。在這裏就可以將 application.properties 配置文件中前綴是 formatter 的配置項映射到 DateFormatProperties 類中。

3.3 創建配置類

然後我們需要創建一個配置類,這個配置類能夠將核心功能類注入到 Ioc 容器,使得在其他引用此 starter 的項目中能夠使用自動配置的功能。

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.text.SimpleDateFormat;
/**
 * 配置信息實體類
 * @author Planeswalker23
 * @date 2020-05-25
 */
@Configuration
@EnableConfigurationProperties(DateFormatProperties.class)
@ConditionalOnProperty(prefix = "formatter", name = "enabled", havingValue = "true")
public class DateFormatConfiguration {
    private DateFormatProperties dateFormatProperties;
    public DateFormatConfiguration(DateFormatProperties dateFormatProperties) {
        this.dateFormatProperties = dateFormatProperties;
    }
    @Bean(name = "myDateFormatter")
    public SimpleDateFormat myDateFormatter() {
        System.out.println("start to initialize SimpleDateFormat with pattern: " + dateFormatProperties.getPattern());
        return new SimpleDateFormat(dateFormatProperties.getPattern());
    }
}

這裏 starter 的功能是基於 SimpleDateFormat 類的,其實就是解析配置文件中的指定格式,將其設置爲 SimpleDateFormat 的 pattern 屬性,然後將 SimpleDateFormat 類作爲“組件”註冊在 Ioc 容器中,這樣我們就可以在引用了該 starter 的項目中使用自定義格式化功能了。

@Configuration 註解的作用是將 DateFormatConfiguration 類作爲配置類注入容器

@
EnableConfigurationProperties 註解的作用是開啓資源實體類的加載,也就是說開啓配置文件映射爲資源實體類的功能。

@ConditionalOnProperty 註解是開啓條件化配置,也就是說只有在配置文件中的 formatter.enabled 屬性的值爲 true 時,這個 starter 纔會生效。

3.4 指定自動裝配

至此開發的業務代碼就結束了,但是還有一個最重要的步驟就是指定 DateFormatConfiguration 類作爲自動裝配類。

這需要在 resource 目錄下創建 MATE-INF 文件夾,並創建一個名爲 spring.factories 的文件,然後在文件中寫下

org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.walker.planes.DateFormatConfiguration

這行代碼的意思就是將 DateFormatConfiguration 設置爲自動裝配類,在 SpringBoot 工程啓動時會去掃描 MATE-INF 文件夾的 spring.factories 文件,並加載這個文件中指定的類,啓動自動裝配功能。

3.5 發佈&測試

然後在命令行中敲下 mvn clean install 命令,當看到下面的輸出後,自定義的 starter 就可以作爲一個依賴被引用了。

[INFO] -----------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -----------------------------------------------------------
[INFO] Total time:  1.470 s
[INFO] Finished at: 2020-05-25T20:24:49+08:00
[INFO] -----------------------------------------------------------

新建一個測試工程,在 pom 文件中加入如下的依賴。

<dependency>
    <groupId>org.walker.planes</groupId>
    <artifactId>date-format-spring-boot-starter</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

然後在 application.properties 文件中開啓自定義 starter 的配置。

formatter.enabled=true
formatter.pattern=yyyy-MM-dd

然後在啓動類中創建一個 Runner 任務,簡單的輸出一個日期類,就像下面這樣。

@SpringBootApplication
public class FirstStarterApplication implements ApplicationRunner {
    public static void main(String[] args) {
        SpringApplication.run(FirstStarterApplication.class, args);
    }
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println(simpleDateFormat.format(new Date()));
    }
    @Resource(type = SimpleDateFormat.class)
    private SimpleDateFormat simpleDateFormat;
}

啓動項目,我們可以看到自動配置生效了,程序將配置文件中指定的格式化樣式覆蓋了默認的 pattern。

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.0.RELEASE)
2020-05-25 20:31:27.144  INFO 5559 --- [           main] org.test.FirstStarterApplication         : Starting FirstStarterApplication on fandeMac-mini.local with PID 5559 (/Users/fan/workspace/first-starter/target/classes started by fan in /Users/fan/workspace/first-starter)
2020-05-25 20:31:27.146  INFO 5559 --- [           main] org.test.FirstStarterApplication         : No active profile set, falling back to default profiles: default
start to initialize SimpleDateFormat with pattern: yyyy-MM-dd
2020-05-25 20:31:27.792  INFO 5559 --- [           main] org.test.FirstStarterApplication         : Started FirstStarterApplication in 0.894 seconds (JVM running for 1.4)
2020-05-25

小結

至此,我們已經完成了一個簡單的 SpringBoot Start 的開發了,最後來總結一下一個 starter 的開發流程。

引入 spring-boot-autoconfigure 依賴

創建配置實體類

創建自動配置類,設置實例化條件(@Conditionalxxx註解,可不設置),並注入容器

在 MATE-INF 文件夾下創建 spring.factories 文件夾,激活自動配置。

在 maven 倉庫發佈 starter

推薦閱讀:

馬士兵教育2020最新最全版馬士兵高併發多線程450分鐘教程,【從入門到精通】

面試美團被JVM慘虐?阿里P9架構師用500分鐘把JVM從入門講到實戰#合集

硬核!清華雙大佬馬士兵VS周志磊把TCP協議、高併發負載均衡、多線程、JVM底層給講清楚了

四十歲的Java程序員活該被淘汰?馬士兵給所有Java程序員的忠告,告知當代應屆生進大廠的祕訣

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章