15_SpringBoot 事件监听机制

image-20200708160944615

image-20220319155642419

背景:

知道什么叫“以增量的方式应对变化的需求”吗?听过Spring监听机制吗?

image-20220319160420380

1. Spring事件机制

image-20220319162914908

1.1 环境准备

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
43
44
45
46
47
48
<?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.6.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.jerry</groupId>
<artifactId>springevent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springevent</name>
<description>Demo project for Spring Boot</description>
<packaging>jar</packaging>

<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

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

</project>

1.2 发布方服务

eg: 订单服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 订单服务
*
* @author Jerry(姜源)
* @date 2022-03-19 13:56
*/
@Service
public class OrderService {

@Autowired
private EventPublisher eventPublisher;

public void order() {
//下单成功
System.out.println("下单成功...");
//发布通知(true:异步执行, false:同步执行)
eventPublisher.publishEvent(new OrderSuccessEvent(this), true);
System.out.println("main线程结束...");
}
}

1.3 事件监听

eg: 物流服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 物流服务,监听OrderSuccessEvent
*
* @author Jerry(姜源)
* @date 2022-03-19 13:56
*/
@Service
public class CarService implements ApplicationListener<OrderSuccessEvent> {

@Override
public void onApplicationEvent(OrderSuccessEvent event) {
this.dispatch();
}

/**
* 发车
*/
@Order(1)
public void dispatch() {
System.out.println("发车咯...");
}
}

eg: 短信服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 短信服务
*
* @author Jerry(姜源)
* @date 2022-03-19 13:56
*/
@Service
public class SmsService {

/**
* 发送短信
*
* @EventListener 指定监听的事件类, 注解方式可以不用实现ApplicationListener
* @Order 默认是最低优先级,值越小优先级越高
* @author Jerry(姜源)
* @date 2022-03-19 15:32
*/
@Order(0)
@EventListener(OrderSuccessEvent.class)
public void sendSms() {
System.out.println("发送短信...");
}
}

1.4 自定义事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 自定义事件,继承ApplicationEvent
*
* @author Jerry(姜源)
* @date 2022-03-19 13:56
*/
public class OrderSuccessEvent extends ApplicationEvent {

/**
* 创建一个新的应用程序事件。
*
* @param source 事件最初发生的对象(从不 {@code null})
*/
public OrderSuccessEvent(Object source) {
super(source);
}
}

1.5 事件发布器

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
@Component
public class EventPublisher {

@Autowired
private ApplicationContext applicationContext;

/**
* 发布 Spring 事件
*
* @param source 事件源
* @param asyncBool 异步标记
* @return void
* @author Jerry(姜源)
* @date 2022-03-19 14:47
*/
public void publishEvent(Object source, Boolean asyncBool) {
if (asyncBool) {
//异步线程任务
ThreadPoolExecutor executor = new ThreadPoolExecutor(
1, 1, 5, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10),
r -> new Thread(r, "Spring事件发布线程_Thread_" + r.hashCode()),
new ThreadPoolExecutor.DiscardOldestPolicy()
);
executor.execute(() -> applicationContext.publishEvent(source));
executor.shutdown();
} else {
applicationContext.publishEvent(source);
}
}
}

2. 测试验证

1
2
3
4
5
6
7
8
9
10
11
12
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringEventTest {

@Autowired
private OrderService orderService;

@Test
public void testSpringEvent() {
orderService.order();
}
}

image-20220319162953304

当然了,最后还是要说一句,项目并发高了以后,也不可能用Spring监听机制的,MQ会更合适。


15_SpringBoot 事件监听机制
https://janycode.github.io/2022/03/19/08_框架技术/04_SpringBoot/15_SpringBoot 事件监听机制/
作者
Jerry(姜源)
发布于
2022年3月19日
许可协议