SpringBoot自定义Starter
# Starter 命名规范
什么是 Starter,比如spring-boot-starter-data-redis
就是一个标准的官方 Starter 组件。Starter 内部定义了相关 jar 包的依赖,而我们不需要一个一个去引入相关 jar,实现了 bean 自动装配,自动声明并且加载 properties 文件属性配置。
命名规范:
- 官方:spring-boot-starter-模块名称
- 自定义:模块名称-spring-boot-starter
# 手写一个 starter 组件
基于前面所讲自动装配原理,我们从 0 到 1 写一个自定义的 Starter 组件来加深大家对自动装配的理解。下面是基于消息中间件 RabbitMQ 写一个自定义 Starter 组件,不了解 RabbitMQ 的朋友可以参阅我之前的文章,到具体的客户端使用该组件详细步骤。
- 创建一个名为 mq-spring-boot-starter 的 maven 项目 目录结构:
添加 jar 包依赖,pom 文件中引入 spring-rabbit(spring 对 RabbitMQ 的一个封装):
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>2.3.10</version>
<scope>compile</scope>
</dependency>
2
3
4
5
6
- 定义属性类
该属性类配置 RabbitMQ 的 IP、端口、用户名、密码等信息。由于只是一个简单的 Demo,只定义了一些简单的参数。前缀为 fire.mq,对应 properties/yml 中的属性。
/**
* @author Mr.Fire
* @date 2021/8/15 17:35
* @desc
*/
@ConfigurationProperties(prefix = "fire.mq")
public class RabbitMqProperties {
private String address = "localhost";
private int port = 5672;
private String userName;
private String password;
...
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 定义配置类
- 通过 @Configuration 声明为一个配置类
- @EnableConfigurationProperties(RabbitMqProperties.class):导入属性类
- @Bean 注解方式上声明一个 connectionFactory 的 bean 对象,设置用户名密码等
- 通过 FireRabbitTemplate 的构造方法传入 connectionFactory
- @ConditionalOnClass:表示一个条件,当前 classpath 下有这个 class,才会实例化一个 Bean
注:这里的 FireRabbitTemplate 为我自定义的一个类,继承自了 RabbitTemplate,下面步骤有写。
/**
* @author Mr.Fire
* @date 2021/8/15 17:40
* @desc
*/
@Configuration
@EnableConfigurationProperties(RabbitMqProperties.class)
public class RabbitMqConfig {
@Bean
@ConditionalOnClass(ConnectionFactory.class)
FireRabbitTemplate fireRabbitTemplate(ConnectionFactory connectionFactory) {
FireRabbitTemplate rabbitTemplate = new FireRabbitTemplate(connectionFactory,"fireMQ");
//数据转换为 json 存入消息队列
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
return rabbitTemplate;
}
@Bean
ConnectionFactory connectionFactory(RabbitMqProperties rabbitMqProperties){
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("localhost");
connectionFactory.setHost(rabbitMqProperties.getAddress());
connectionFactory.setPort(rabbitMqProperties.getPort());
connectionFactory.setUsername(rabbitMqProperties.getUserName());
connectionFactory.setPassword(rabbitMqProperties.getPassword());
return connectionFactory;
}
}
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
- 自定义的 RabbitTemplate
定义一个有 name 的 RabbitTemplate,继承自 RabbitTemplate,通过名字测试可以直观看到效果。
注:RabbitTemplate 是 Spring 对 RabbitMQ 的一个封装好的模板接口,类似于 RedisTemplate。
/**
* @author Mr.Fire
* @date 2021/8/15 17:42
* @desc
*/
public class FireRabbitTemplate extends RabbitTemplate {
private String name="fireMQ";
public FireRabbitTemplate(ConnectionFactory connectionFactory,String name) {
super(connectionFactory);
this.name = name;
}
public String getName() {
return name;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- 关键一步,在 resources 目录下新建 spring.factories 文件,key-value 形式配置写好的 Config 类。使 Spring Boot 可以扫描到文件完成自动装配。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.fire.mq.rabbitmq.RabbitMqConfig
2
至此,一个非常简单的自定义 Starer 组件已经完成。我们只需要安装到本地仓库,其他项目就可以引用该组件了。
- 执行命令
mvn install
到本地仓库。
注:安装前需要把 spring-boot-maven-plugin 给去掉。
# 测试
接下来我们新建一个测试工程来引入我们写好的 Starter 组件,测试一下效果。
- 新建一个简单的测试工程 starter-cilent,目录结构如下:
- 引入自定义的 Starter:
<dependency>
<groupId>com.fire</groupId>
<artifactId>mq-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
2
3
4
5
- 编写测试代码
这里写一个 Web 接口用来模拟发消息,发到对应的 helloQueue 队列中,监听这个队列的消费者就能消费这条消息。
定义 rest 接口:注入自定义 Starter 组件中的 FireRabbitTemplate 模板接口类,调用发消息的方法。
/**
* @author Mr.Fire
* @date 2021/8/15 17:48
* @desc
*/
@RestController
public class MqRestController {
@Autowired
FireRabbitTemplate rabbitTemplate;
@GetMapping("/send")
public String sendMsg(){
String msg = "这是一条来自"+rabbitTemplate.getName()+"的消息!";
rabbitTemplate.convertAndSend("helloQueue",msg);
return "success";
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
定义队列:
@Configuration
public class HelloQueue {
@Bean
public org.springframework.amqp.core.Queue queue() {
return new org.springframework.amqp.core.Queue("helloQueue");
}
}
2
3
4
5
6
7
8
定义消费者,监听 helloQueue 队列,并打印收到的消息。
@Configuration
public class Consumer {
@RabbitListener(queues = "helloQueue")
@RabbitHandler
public void receive(String msg) {
System.out.println("Consumer 收到消息:" + msg);
}
}
2
3
4
5
6
7
8
9
10
- 配置文件 appliction.properties
这里默认本地已经安装 RabbitMQ,需要的朋友可以看我的前一篇文章。
fire.mq.address=localhost
fire.mq.port=5672
fire.mq.username=guest
fire.mq.password=guest
server.port=8081
2
3
4
5
- 启动测试
浏览器输入 http://localhost:8081/send,看控制台输出:
这说明自己写的 Starter 组件已经生效,成功收到“fireMq”发来的消息。
# 总结
通过手写一个简单的自定义 Starter 组件加深对自动装配的理解。有需要的朋友可以动手写一个Starter组件进行加深理解。
案例demo:
mq-spring-boot-starter: https://gitee.com/firegitspace/mq-spring-boot-starter.git (opens new window)
starter-cilent: https://gitee.com/firegitspace/starter-cilent.git (opens new window)