编写一个 springboot starter 是一个很实用的需求, 特别是当想要封装一些通用的功能或配置, 以便在不同的项目中低成本复用; springboot starter 本质上是一个 maven 或 gradle 模块, 它包含了自动配置类、依赖管理和其他必要的资源;

核心类定义

我们编写 springboot starter 的最终目的只是为了更好地引导并加载自己的核心服务类, 而这个核心类本身是不用感知 springboot starter 的存在的, 它可以定义在一个完全独立的 maven 模块中, 而与之配套的 springboot starter maven 模块则应该依赖它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.xxx;

public class XXXService {

private final String message;

public XXXService(String message) {
this.message = message;
}

public String getMessage() {
return message;
}
}

starter 编写流程

添加依赖

创建一个专门用作 starter 的 maven 项目, 对 pom.xml 添加 springboot 相关依赖, 确保项目是一个 spring-boot-starter 类型的项目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<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.xxx</groupId>
<artifactId>xxx-spring-boot-starter</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

<properties>
<java.version>1.8</java.version>
<spring-boot.version>2.5.4</spring-boot.version>
</properties>

<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
</dependency>

<!-- Spring Boot Autoconfigure -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${spring-boot.version}</version>
</dependency>

<!-- Optional: Add other dependencies your starter might need -->
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

创建配置属性 Properties

创建一个配置属性类, 用于从 application.propertiesapplication.yml 中读取配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.xxx;

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

@ConfigurationProperties(prefix = "xxx")
public class XXXProperties {

private String message = "Default Message";

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}
}

创建 AutoConfiguration

创建一个自动配置类, 这个类将包含 starter 的核心引导逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.xxx;

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
@ConditionalOnClass(XXXService.class)
@EnableConfigurationProperties(XXXProperties.class)
public class XXXAutoConfiguration {

private final XXXProperties properties;

public XXXAutoConfiguration(XXXProperties properties) {
this.properties = properties;
}

/**
* 核心类的引导与加载
*/
@Bean
@ConditionalOnMissingBean
public XXXService xxxService() {
return new XXXService(properties.getMessage());
}
}

注册 AutoConfiguration

src/main/resources/META-INF 目录下创建一个 spring.factories 文件,用于注册自动配置类。

1
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.xxx.XXXAutoConfiguration

在 springboot 应用中使用

打包并发布后, 可在其他 Spring Boot 应用中, 通过添加依赖来使用 starter:

1
2
3
4
5
<dependency>
<groupId>com.xxx</groupId>
<artifactId>xxx-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>

然后在 application.properties 中配置目标属性:

1
xxx.message=test my spring boot starter!

可以通过注入 XXXService 来测试 starter 是否正常工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RestController
public class XXXController {

private final XXXService xxxService;

public XXXController(XXXService xxxService) {
this.xxxService = xxxService;
}

@GetMapping("/message")
public String getMessage() {
return xxxService.getMessage();
}
}