1 SmartApplicationListener介绍
Spring ApplicationEvent以及对应的Listener提供了一个事件监听、发布订阅的实现,内部实现方式是观察者模式,可以解耦业务系统之间的业务,提供系统的可拓展性、复用性以及可维护性。
Spring 提供的ApplicationEvent & Listener有3种实现方式:本章节使用的方式:SmartApplicationListener的使用方式。
SmartApplicationListener接口继承了ApplicationListener 和 Ordered接口,实现了事件监听和排序的功能。
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
/**
* Determine whether this listener actually supports the given event type(判断这个监听器是否真支持给定的事件类型).
* @param eventType the event type (never {@code null})(事件类型)
*/
boolean supportsEventType(Class<? extends ApplicationEvent> eventType);
/**
* Determine whether this listener actually supports the given source type(判断这个监听器是否支持给定的源类型).
* <p>The default implementation always returns {@code true}.
* @param sourceType the source type, or {@code null} if no source
*/
default boolean supportsSourceType(@Nullable Class<?> sourceType) {
return true;
}
/**
* Determine this listener's order in a set of listeners for the same event(确定此监听器在同一事件的一组监听器中的顺序).
* <p>The default implementation returns {@link #LOWEST_PRECEDENCE}.
*/
@Override
default int getOrder() {
return LOWEST_PRECEDENCE;
}
/**
* Return an optional identifier for the listener(返回监听器的可选标识符).
* <p>The default value is an empty String.
* @since 5.3.5
* @see EventListener#id
* @see ApplicationEventMulticaster#removeApplicationListeners
*/
default String getListenerId() {
return "";
}
}
2 SmartApplicationListener代码实现
SmartApplicationListener是高级监听器,是ApplicationListener的子类,能够实现有序监听。
假设订单在创建之后(业务层service)需要将订单创建的消息发送通知到Kafka集群做进一步处理,之前的伪代码可能为:
package com.zs.service;
@Service
public class OrderManager {
/**
* 模拟创建订单
*/
public void createOrder() {
Long orderId = 12345L;
OrderDTO order = new OrderDTO();
order.setOrderId(orderId);
order.setCreateTime(new Date());
// 2、调用第三方的接口, 去通知订单创建;这样的方式耦合性太高了,不建议采用这种方式。
// invoke service...
// 建议使用事件发布机制解耦
// ...
}
}
2.1 SmartApplicationListener实现事件发布机制
(1)首先定义事件源对象,对象中包含需要发送的基本信息。
package com.zs.pojo;
@Data
public class OrderDTO {
private long orderId;
private Date createTime;
}
(2)定义发生的事件:
package com.zs.event;
public class OrderCreateEvent extends ApplicationEvent {
@Getter
private OrderDTO orderDTO;
/**
* 重写构造函数
* @param source 发生事件的源对象
* @param orderDTO 事件对应的信息
*/
public OrderCreateEvent(Object source, OrderDTO orderDTO) {
super(source);
this.orderDTO = orderDTO;
}
}
(3)事件发布:
package com.zs.publish;
public interface EventPublishService<T> {
void publishEvent(T event);
}
package com.zs.publish.impl;
@Service("springEventPublishService")
public class SpringEventPublishServiceImpl implements EventPublishService<ApplicationEvent>, ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void publishEvent(ApplicationEvent event) {
applicationContext.publishEvent(event);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
(4)事件监听:当有事件发生时,监听到事件的变更通知做进一步处理:
package com.zs.listener;
@Component
public class OrderCreateEventListener implements SmartApplicationListener {
/**
* 判断这个监听器是否真支持给定的事件类型
* @param eventClass
* @return
*/
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventClass) {
return eventClass == OrderCreateEvent.class;
}
/**
* 判断这个监听器是否支持给定的源类型
* @param sourceType
* @return
*/
@Override
public boolean supportsSourceType(@Nullable Class<?> sourceType) {
return true;
}
/**
* 定义事件监听器的顺序
* @return
*/
@Override
public int getOrder() {
return 0;
}
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
OrderCreateEvent orderCreateEvent = (OrderCreateEvent) applicationEvent;
OrderDTO orderDTO = orderCreateEvent.getOrderDTO();
System.out.println("=== 收到订单创建事件 ===" + orderDTO);
// 业务逻辑
// ......
}
}
(5)改造:如何使用Spring事件发布机制实现业务解耦:
package com.zs.service;
@Service
public class OrderManager {
@Autowired
@Qualifier("springEventPublishService")
private EventPublishService eventPublishService;
/**
* 模拟创建订单
*/
public void createOrder() {
Long orderId = 12345L;
OrderDTO order = new OrderDTO();
order.setOrderId(orderId);
order.setCreateTime(new Date());
// 使用事件发布机制解耦
eventPublishService.publishEvent(new OrderCreateEvent(this, order));
}
}
(6)测试:
package com.zs.controller;
@RestController
public class OrderController {
@Autowired
private OrderManager orderManager;
@RequestMapping("/order/create")
public void createOrder() {
orderManager.createOrder();
}
}
上面使用Spring SmartApplicationListener实现的事件驱动模型,使kafka消息发送从订单主流程业务中解耦出来。当然,上述只是个例子,光从例子上看并不能体现应用Spring的事件发布机制的简洁性。这个demo只是为了介绍Spring SmartApplicationListener的使用,在实际应用中可能有更适合用此方法实现业务解耦的场景,如订单状态变更时发送消息就可以使用本文介绍的方法。
3 SmartApplicationListener支持异步使用示例
应用SmartApplicationListener实现的Spring 事件驱动模型可以配合使用Spring提供的@Async
注解实现异步调用。@Async
的实现是利用配置好的线程池任务ThreadPoolTaskExecutor执行注解所在的方法。
@Configuration
@EnableAsync
public class ListenerAsyncConfiguration implements AsyncConfigurer {
/**
* 获取异步线程池执行对象
* @return
*/
@Override
public Executor getAsyncExecutor() {
//使用Spring内置线程池任务对象
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
//设置线程池参数
taskExecutor.setCorePoolSize(5);
taskExecutor.setMaxPoolSize(10);
taskExecutor.setQueueCapacity(25);
taskExecutor.initialize();
return taskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}
使用的时候,只要加上@Async注解即可:
@Component
public class OrderEventListener implements SmartApplicationListener {
@Override
@Async
public void onApplicationEvent(ApplicationEvent applicationEvent) {
// 获取注册用户信息
OrderStatusMsgEvent orderStatusMsgEvent = (OrderStatusMsgEvent) applicationEvent;
OrderDTO orderInfo = orderStatusMsgEvent.getOrderDTO();
// 模拟kafka发送
// kafkaProducer.sendMsg(orderInfo);
System.out.println("======kafka发送成功====");
}
}