Spring中事件的发布订阅

一、介绍

在Spring框架中,ApplicationEventPublisher是一个接口,用于发布应用程序事件。它允许应用程序的不同组件之间进行解耦,实现事件驱动的开发模式。

通过ApplicationEventPublisher,我们可以将自定义的事件发布到应用程序的上下文中,然后其他组件可以注册为ApplicationListener来监听这些事件。ApplicationListener是另一个接口,用于接收和处理应用程序事件。

当事件被发布时,ApplicationEventPublisher会通知所有注册的ApplicationListener,并将事件对象传递给它们。这样,监听器就可以根据事件的类型进行相应的处理逻辑,完成业务逻辑的触发和处理。

使用ApplicationEventPublisherApplicationListener可以实现松耦合的事件驱动编程,提高代码的可维护性和扩展性。它们是Spring框架中事件机制的核心组件之一。

不啰嗦,直接看如何编写代码

二、代码

声明一个事件,TestEvent.java,需要继承ApplicationEvent.java,并传递一个对象

1
2
3
4
5
6
7
8
9
10
11
12
package com.banmoon.event.test;

import com.banmoon.obj.request.TestEventRequest;
import org.springframework.context.ApplicationEvent;

public class TestEvent extends ApplicationEvent {

public TestEvent(TestEventRequest dto) {
super(dto);
}

}

这边这个对象,选择了TestEventRequest,java,里面可以放事件相关的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.banmoon.obj.request;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.NotBlank;

@Data
@ApiModel("发布订阅测试-入参")
public class TestEventRequest {

@NotBlank
@ApiModelProperty(value = "名称标识", required = true)
private String name;

@NotBlank
@ApiModelProperty(value = "说明", required = true)
private String description;

}

事件有了,如何进行发布呢?自己注入直接使用ApplicationEventPublisher.java也行,这边选择实现ApplicationEventPublisherAware.java。都是一样的

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
package com.banmoon.event;

import lombok.Data;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;

import javax.annotation.Nonnull;

@Data
@Component
public class BanmoonApplicationEventPublisherAware implements ApplicationEventPublisherAware {

private ApplicationEventPublisher applicationEventPublisher;

@Override
public void setApplicationEventPublisher(@Nonnull ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}

public void publishEvent(ApplicationEvent event) {
applicationEventPublisher.publishEvent(event);
}
}

发布有了,订阅来看看TestListener.java

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

import com.banmoon.obj.request.TestEventRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class TestListener {

@EventListener(TestEvent.class)
public void listener(TestEvent event) {
TestEventRequest dto = (TestEventRequest) event.getSource();
log.info("订阅监听消息:{}", dto);
}

}

三、测试

来测试一下

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
package com.banmoon.controller;

import com.banmoon.business.obj.dto.ResultData;
import com.banmoon.event.BanmoonApplicationEventPublisherAware;
import com.banmoon.event.test.TestEvent;
import com.banmoon.obj.request.TestEventRequest;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;

@Slf4j
@Validated
@Api(tags = "发布订阅测试")
@RestController
@RequestMapping("/event")
public class TestEventController {

@Resource
private BanmoonApplicationEventPublisherAware applicationEventPublisherAware;

@ApiOperation("发布测试事件")
@PostMapping("/publishTestEvent")
public ResultData<Void> publishTestEvent(@RequestBody @Valid TestEventRequest req) {
TestEvent testEvent = new TestEvent(req);
applicationEventPublisherAware.publishEvent(testEvent);
return ResultData.success();
}

}

image-20240310172209277

四、最后

我是半月,你我一同共勉