SpringBoot手写starter

前言

使用SpringBoot的过程中,一定看到过各种 spring-boot-starter 比如第三方扩展的有 druid-spring-boot-starter,mybatis-plus-boot-starte r等,官方的有spring-boot-starter-web 等。这里注意他们的命名规则,第三方扩展的命名规则是 xxx-spring-boot-starter, 官方的命名规则是 spring-boot-starter-xxx

starter的作用

在业务代码开发中,可以封装一些公用的会在多个项目中使用的工具类,相当于是项目级别的Method,如果公司有中间件团队也是会采用starter这种方式提供给业务团队使用。有效的减少了代码重复硬拷贝以及繁杂的配置,统一集成进starter,也有利于后期版本的迭代管理。

自己实现一个starter

创建 Maven项目

  1. 根据第三方扩展的命名规则 首先创建一个项目名称为 sms-spring-boot-starter。
  2. 删除启动(带有@SpringBootApplication)类。
  3. pom.xml依赖修改
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
<?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">
<parent>
<artifactId>hexo-blog-demo</artifactId>
<groupId>org.pepsiyoung</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<groupId>com.pepsiyoung</groupId>
<artifactId>sms-spring-boot-starter</artifactId>

<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</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>

创建 SmsProperties

1
2
3
4
5
6
7
8
@ConfigurationProperties(prefix = "sms")
@Data
public class SmsProperties {
/**
* 运营商(默认电信)
*/
private String operator = "电信";
}

配合 spring-boot-configuration-processor 能够在开发过程中通过IDE的处理给我们更多的便捷提示。这是因为在项目中包含了meta-data,编译后会在target/classes/META-INF/文件夹下生成spring-configuration-metadata.json,有兴趣的同学可以看下文件目录。

@Data 注解是使用了 Lombok
@ConfigurationProperties(prefix = “sms”) 设置前缀 (sms.operator = xxx)
不需要在resources下创建application.yml文件

创建 Service

  1. 创建 MessageService 类假装他有一个sms方法能够发送消息。
1
2
3
4
5
6
7
8
9
private final SmsProperties smsProperties;

public MessageService(SmsProperties smsProperties) {
this.smsProperties = smsProperties;
}

public String sms(String phone, String content) {
return String.format("假装发送[%s]给手机号[%s]的用户「%s」", phone, content, smsProperties.getOperator());
}

创建自动配置类

  1. 创建 AutoConfiguration 类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@EnableConfigurationProperties(SmsProperties.class)
@Configuration
public class AutoConfiguration {

final
SmsProperties smsProperties;

public AutoConfiguration(SmsProperties smsProperties) {
this.smsProperties = smsProperties;
}

@Bean
public MessageService messageService() {
return new MessageService(smsProperties);
}
}
  1. 在resources/META-INF/ 下创建 spring.factories 文件
1
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.pepsiyoung.sms.config.AutoConfiguration

测试验证

  1. 在IDEA中,执行mvn install。
  2. 完成后,在其他项目的pom文件中引入。
1
2
3
4
5
6
<!-- 引入自定义starter-->
<dependency>
<groupId>com.pepsiyoung</groupId>
<artifactId>sms-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
  1. 写一个 controller 做测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RestController
@RequestMapping("sms")
public class smsController {

@Autowired
MessageService messageService;

@GetMapping("test")
public String test() {
String phone = "18822233344";
String content = "天气变冷";
return messageService.sms(phone, content);
}
}

发现 messageService 能够正常使用 输出结果:假装发送[18822233344]给手机号[天气变冷]的用户「电信」

  1. 也可以在yml文件中配置sms.operator 如果不设置默认就是电信
1
2
sms:
operator: 联通

再运行 输出结果:假装发送[18822233344]给手机号[天气变冷]的用户「联通」

总结

今天我们了解了 spring-boot-configuration-processor 的作用,并且动手实现了一个自定义starter。过程并不复杂,那是因为spring帮我们做了很多事。spring.factories里配置的类是为了通知 Spring Boot 需要加载哪些自动装配类。Spring boot 中的 starter 是非常重要的机制,抛弃繁杂的配置,统一集成进starter。可以理解为是项目及别的Method。
最后我把完整的代码放在Github上有需要的同学可以start这个项目。

https://github.com/pepsiyoung/hexo-blog-demo/tree/main/sms-spring-boot-starter

如有错误欢迎指正。