目录
一、ApplicationListener概述:
二、ApplicationListener是什么?
三、内置事件:
四、使用场景:
五、ApplicationListener实战案例:
5.1 基本业务场景代码搭建
5.1.1 创建订单服务
5.1.2 使用controller进行调用
5.1.3 测试
5.2 业务升级迭代
5.3 优化代码
5.3.1 创建事件
5.3.2 事件监听器
5.3.3 事件发布
5.3.4 测试
接下来我们首先来看看ApplicationListener的基本概念、一些内置的事件以及使用场景。
ApplicationListener可以监听某个事件的event,触发时机可以穿插在业务方法执行过程中,用户可以自定义某个业务事件。但是spring内部也有一些内置事件,这种事件,可以穿插在启动调用中。我们也可以利用这个特性,来自己做一些内置事件的监听器来达到和前面一些触发点大致相同的事情
Spring内部也有一些内置事件,这种事件,可以穿插在启动调用中。我们也可以利用这个特性,来自己做一些内置事件的监听器来达到和前面一些触发点大致相同的事情。
接下来罗列下spring主要的内置事件:
(1)ContextRefreshedEvent ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用。 (2)ContextStartedEvent 当使用ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。 (3)ContextStoppedEvent 当使用ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作 (4)ContextClosedEvent 当使用ConfigurableApplicationContext接口中的 close()方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启 (5)RequestHandledEvent 这是一个web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件
业务场景描述:在很多平台订单创建成功之后,会给业务操作者发送一条短信进行提醒。
针对这样的业务场景,常规下我们会怎么编码以及使用了ApplicationListener会怎么编码。
首先我们根据常规搭建一套基本的代码结构。
构建一个订单服务,主要功能是创建订单,并且发送短信。
package com.test.service;
import org.springframework.stereotype.Service;
/**
* 订单服务
*/
@Service
public class OrderService {
/**
* 创建订单.
*/
public void createOrder(){
//1. 创建订单: 生成订单信息,然后保存到数据库.
System.out.println("创建订单 - 生成订单信息,然后保存到数据库");
//2. 发送短信: 调用短信服务,给手机号发送短信信息.
System.out.println("发送短信 - 调用短信服务,给手机号发送短信信息");
}
}
编写一个controller调用订单服务,方便测试:
package com.test.controller;
import com.kfit.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 订单的Controller
*/
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@RequestMapping("/createOrder")
public String createOrder(){
orderService.createOrder();
return "创建成功!";
}
}
启动应用进行测试,访问地址如下地址:
http://127.0.0.1:8080/createOrder
现有新需求:需要加一个微信通知的功能,常规做法会在OrderService进行添加微信通知的代码逻辑,如下所示:
package com.test.service;
import org.springframework.stereotype.Service;
/**
* 订单服务
*/
@Service
public class OrderService {
/**
* 创建订单.
*/
public void createOrder(){
//1. 创建订单: 生成订单信息,然后保存到数据库.
System.out.println("创建订单 - 生成订单信息,然后保存到数据库");
//2. 发送短信: 调用短信服务,给手机号发送短信信息.
System.out.println("发送短信 - 调用短信服务,给手机号发送短信信息");
//3. 发送微信 - 调用微信公众号的通知服务,进行发送。
System.out.println("发送微信 - 调用微信公众号的通知服务,进行发送");
}
}
存在问题:每次创建订单需要加新功能(如新的通知方式),则要修改原有的类,难以维护,违背设计模式的原则: (1)单一职责:订单保存功能,夹杂了消息通知这些功能 (2)开闭原则:对拓展开放,对修改关闭
优化方案:使用观察者模式,使创建订单和消息通知进行分离,低耦合。可以选择消息队列,Spring事件机制等,本文选择Spring事件机制。
使用事件机制的,那么需要先定义订单的事件,然后使用监听器对事件进行监听,最后就是在创建订单的时候进行事件的发布。
构建OrderCreateEvent事件,继承接口ApplicationEvent:
package com.test.service;
import org.springframework.context.ApplicationEvent;
/**
* 订单创建事件
*/
public class OrderCreateEvent extends ApplicationEvent {
private String orderInfo;//订单信息
public OrderCreateEvent(Object source,String orderInfo){
super(source);
this.orderInfo = orderInfo;
}
public String getOrderInfo() {
return orderInfo;
}
public void setOrderInfo(String orderInfo) {
this.orderInfo = orderInfo;
}
}
事件监听,主要是短信发送监听和微信发送监听。
SmsListener:
package com.test.service;
import com.kfit.order.order.event.OrderCreateEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* OrderCreateEvent的短信监听.
*/
@Component
public class SmsListener implements ApplicationListener {
@Override
public void onApplicationEvent(OrderCreateEvent event) {
//. 发送短信: 调用短信服务,给手机号发送短信信息.
System.out.println("发送短信 - 调用短信服务,给手机号发送短信信息;订单信息:"+event.getOrderInfo());
}
}
WechatListener:
package com.test.service;
import com.kfit.order.order.event.OrderCreateEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* WechatListener的微信监听.
*/
@Component
public class WechatListener implements ApplicationListener {
@Override
public void onApplicationEvent(OrderCreateEvent event) {
//. 发送微信 - 调用微信公众号的通知服务,进行发送。
System.out.println("发送微信 - 调用微信公众号的通知服务,进行发送;订单信息:"+event.getOrderInfo());
}
}
事件发布可以使用ApplicationContext或者ApplicationEventPublisher的publishEvent方法进行发布,修改一下OrderService的代码:
package com.test.service;
import com.test.service.OrderCreateEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
/**
* 订单服务
*/
@Service
public class OrderService {
@Autowired
private ApplicationContext applicationContext;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
/**
* 创建订单.
*/
public void createOrder(){
//1. 创建订单: 生成订单信息,然后保存到数据库.
System.out.println("创建订单 - 生成订单信息,然后保存到数据库");
//2. 发布事件
OrderCreateEvent orderCreateEvent = new OrderCreateEvent(this,"orderNo:20230815");
applicationContext.publishEvent(orderCreateEvent);
//applicationEventPublisher.publishEvent(orderCreateEvent);//也可以
}
启动应用进行测试,访问地址如下地址:
http://127.0.0.1:8080/createOrder
若要先执行发送微信的监听的话,在类上添加@Order注解即可,值越小越执行,也就是@Order(1)会在@Order(2)之前执行。
源码:https://download.csdn.net/download/u011974797/88280036
原文:springboot ApplicationListener 观察者模式实际应用场景