SpringBoot 异步事件实现异步(ApplicationEventPublisher、ApplicationEvent)
当把一个事件发布到Spring提供的ApplicationContext中,被监听器侦测到,就会执行对应的处理方法。
实现方法
自定义需要发布的事件类,需要继承ApplicationEvent类或PayloadApplicationEvent<T>(该类也仅仅是对ApplicationEvent的一层封装)
使用@EventListener来监听事件
使用ApplicationEventPublisher来发布自定义事件(@Autowired注入即可)
好处
可以使核心业务与子业务进行解耦,也方便后期的业务的扩展。如新用户注册之后,需要发放优惠券,此时可以在保存用户之后,发布一个新用户的注册成功事件
,通过监听该事件来实现发放优惠券的功能。后期新增一个对新用户进行xxx功能,此时可以新写一个监听注册成功事件
的监听器,来处理新的业务逻辑,而不需要修改之前的注册逻辑。
注意事项
1、监听器方法中一定要try-catch异常,否则会造成发布事件(有事务的)的方法进行回滚
2、可以使用@Order注解来控制多个监听器的执行顺序,@Order传入的值越小,执行顺序越高
3、对于需要进行s事务监听或不想try-catch runtime异常,可以使用@TransactionalEventListener注解
参考:https://blog.csdn.net/wanping321/article/details/86667216
定时任务关闭未支付的超时订单举例
1、创建事件,继承ApplicationEvent
public class OrderCancelEvent extends ApplicationEvent {
private List<EbOrder> orderList;
public OrderCancelEvent(Object source,List<EbOrder> orderList) {
super(source);
this.orderList = orderList;
}
public List<EbOrder> getOrderList() {
return orderList;
}
}
2、发布订单取消事件(定时任务查询未付款的超时订单,进行关闭)
//修改订单为无效订单
//关闭商户后台系统
dslContext.update(EB_ORDER).set(EB_ORDER.STATUS, OrderStatusEnum.INVALID_ORDER.getStatus()).where(EB_ORDER.ID.in(ids)).execute();
//创建订单取消事件,接收到事件后关闭微信方订单
BaseApplicationContextUtil.getContext().publishEvent(new OrderCancelEvent(this, dslContext.select().from(EB_ORDER).where(EB_ORDER.ID.in(ids)).fetchInto(EbOrder.class)));
3、监听事件
@Component
@Slf4j
public class PayCloseOrderEventListener implements ApplicationListener<OrderCancelEvent> {
@Autowired
private NewEbIPayMethodService newEbIPayMethodService;
@Autowired
private WeixinPayServiceImpl weixinPayService;
@Override
@Async
public void onApplicationEvent(OrderCancelEvent orderCancelEvent) {
List<EbOrder> orderList = orderCancelEvent.getOrderList();
if (CollectionUtils.isEmpty(orderList)) {
return;
}
orderList.forEach(order -> {
Integer payType = order.getPayType();
EbPayMethod payMethod = newEbIPayMethodService.getPayMethodByIden(order.getIdentification(), payType);
if (null != payMethod) {
JSONObject configJson = JSONObject.parseObject(payMethod.getConfig());
if (2 == payType) {
//微信支付
Map<String, String> stringStringMap = weixinPayService.closeOrder(payMethod.getPayCode(),payType, order.getOrderSn());
String returnCode = stringStringMap.get("return_code");
if (WXPayConstants.SUCCESS.equals(returnCode)) {
log.info("订单" + order.getOrderSn() + "微信支付订单关闭成功!");
} else {
log.error("订单" + order.getOrderSn() + "微信支付订单关闭失败!" + stringStringMap.get("return_msg"));
}
} else if (1 == payType) {
//todo 支付宝支付
}
}
});
}
}
4 、BaseApplicationContextUtil 工具类
@Component("context")
public class BaseApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public BaseApplicationContextUtil() {
}
@Override
public void setApplicationContext(ApplicationContext contex) throws BeansException {
applicationContext = contex;
}
public static ApplicationContext getContext() {
return applicationContext;
}
public static Object getBean(String name) throws BeansException {
return applicationContext.getBean(name);
}
demo参考:https://blog.csdn.net/qq_28060549/article/details/81073001
网友评论