springboot事件驱动的配置和示例
定义事件:
public class UserCreatedEvent extends ApplicationEvent {
private final User user;
public UserCreatedEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() {
return user;
}
}
定义线程池,用来异步执行任务:
@Configuration
@EnableAsync
public class CustomAsyncConfig implements AsyncConfigurer {
@Bean
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("MyAsyncThread-");
executor.initialize();
return executor;
}
}
处理事件:
@Component
public class UserEventListener {
@EventListener
@Async
public void handleOrderCreatedEvent(UserCreatedEvent event) {
String name = Thread.currentThread().getName();
System.out.println("listen thread:"+name);
User user = event.getUser();
int i = 5 / 0;//报错用来测试异步执行不影响请求线程
// 在这里可以进行与用户创建相关的后续处理,比如发送通知邮件、更新相关信息等
System.out.println("用户 " + user.getName() + " 已创建,正在进行后续处理,如发送通知邮件等。");
}
}
Controller层示例代码:
@Controller
public class BasicController {
@Autowired
private UserService userService;
// http://127.0.0.1:8080/hello?name=lisi
@RequestMapping("/hello")
@ResponseBody
public String hello(@RequestParam(name = "name", defaultValue = "unknown user") String name) {
User user = new User();
user.setName(name);
user.setAge(18);
userService.createUser(user);
System.out.println("异步报错不受影响!");
return "Hello " + name;
}
}
Service层代码:
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void createUser(User user) {
// 这里可以进行实际的用户创建逻辑,比如保存用户信息到数据库等操作
System.out.println("创建了用户!");
// 假设用户创建成功后,发布用户创建事件,后续异步执行对应事件
eventPublisher.publishEvent(new UserCreatedEvent(this, user));
}
}
学习到的设计模式-观察者模式/发布订阅模式
发布-订阅模式(也称为 Pub/Sub 模式)涉及三个主要组件:
- 发布者(Publisher):负责发布事件到事件通道。
- 订阅者(Subscriber):订阅事件通道,对发布的事件进行响应。
- 事件通道(Event Channel):负责管理事件和订阅者,确保所有发布的事件都能传递给所有订阅者。
利用java自定义实现一个事件驱动模型的例子:
订阅者:
// 订阅者接口
interface Subscriber {
void update(Event event);
}
定义一个事件/主题类:
// 事件
public abstract class Event<T> {
private T source;
public Event(T source) {
this.source = source;
}
public T getSource() {
return source;
}
List<Subscriber> subscribers = new ArrayList<>();
public void subscribe(Subscriber subscriber) {
this.subscribers.add(subscriber);
}
public void unsubscribe(Subscriber subscriber) {
this.subscribers.remove(subscriber);
}
public void notifySubscribers() {
for (Subscriber subscriber : subscribers) {
subscriber.update(this);
}
}
}
事件具体实现类,用户注册事件:
public class UserRegisterEvent<User> extends Event{
public UserRegisterEvent(User source) {
super(source);
}
}
用户注册订阅者:
// 具体订阅者
class UserRegisterSubscriber implements Subscriber {
private String name;
public UserRegisterSubscriber(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void update(Event event) {
System.out.println(name + " 收到消息:" + event.getSource());
}
}
发布者:
// 发布者
class Publisher {
public void publish(Event event) {
event.notifySubscribers();
}
}
定义一个发布者/生产者:
发布者里保存了所有的订阅者或者说是消费者
public class Publisher {
private List<EventConsumer> eventConsumers = new ArrayList<>();
public void addConsumer(EventConsumer consumer) {
eventConsumers.add(consumer);
}
public void removeConsumer(EventConsumer consumer) {
eventConsumers.remove(consumer);
}
public void publishEvent(Event event) {
for (EventConsumer consumer : eventConsumers) {
if (consumer.isSubscribedTo(event.getTopic())) {
consumer.handleEvent(event);
}
}
}
}
测试用例:
public class Main {
public static void main(String[] args) {
User user = new User();
user.setName("alice");
user.setAge(18);
UserRegisterEvent<User> event = new UserRegisterEvent<>(user);
Subscriber subscriber1 = new UserRegisterSubscriber("ethan1");
Subscriber subscriber2 = new UserRegisterSubscriber("ethan2");
Subscriber subscriber3 = new UserRegisterSubscriber("ethan3");
Subscriber subscriber4 = new UserRegisterSubscriber("ethan4");
event.subscribe(subscriber1);
event.subscribe(subscriber2);
event.subscribe(subscriber3);
event.subscribe(subscriber4);
Publisher publisher = new Publisher();
publisher.publish(event);
}
}