观察者模式,定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并完成处理。观察者模式的应用场景是优化执行流程,将非核心流程由串行执行改为异步执行,如下单成功后发送消息。
观察者模式的核心类:
- Observerable:被观察者,核心方法:添加观察者、移除观察者、通知观察者
- Observer:观察者接口
- ObserverImp:观察者实现
实例
public interface Observer {
/**
* 观察者事件
*/
void doEvent();
}
public class EmailObserver implements Observer {
@Override
public void doEvent() {
System.out.println("发送email消息");
}
}
public class MobileNoObserver implements Observer {
@Override
public void doEvent() {
System.out.println("发送短信消息");
}
}
public class Observerable {
private List<Observer> observers = new ArrayList<>();
/**
* 添加观察者
*/
public void addObserver(Observer observer) {
observers.add(observer);
}
/**
* 移除观察者
*/
public void removeObserver(Observer observer) {
observers.remove(observer);
}
/**
* 通知
* @return
*/
public void notifyAllObserver(int state) {
if (state != 1) {
System.out.println("非通知状态");
return;
}
for (Observer observer : observers) {
observer.doEvent();
}
}
}
// 创建订单成功,返回状态
int insert = 1;
// 创建被观察者
Observerable observerable = new Observerable();
// 添加观察者
observerable.addObserver(new EmailObserver());
// 添加观察者
observerable.addObserver(new MobileNoObserver());
// 通知观察者
observerable.notifyAllObserver(insert);
System.out.println("下单成功");
在spring框架中,也有观察者模式的应用,Spring ApplicationEvent事件。
事件机制在一些大型项目中被经常使用,Spring ApplicationEvent就是Spring专门提供的一套事件机制的接口,满足了架构原则上的解耦。
ApplicationContext 通过 ApplicationEvent 类和 ApplicationListener 接口进行事件处理。如果将实现 ApplicationListener 接口的 bean 注入到上下文中,则每次使用 ApplicationContext 发布 ApplicationEvent 时,都会通知该实现 ApplicationListener 接口的 bean。ApplicationEvent 是由 Spring 提供的所有 Event 类的基类。
实例
自定义业务事件子类,继承 ApplicationEvent,通过泛型注入业务模型参数类
public class AbstractGenericEvent<T> extends ApplicationEvent {
public AbstractGenericEvent(Object source) {
super(source);
}
public AbstractGenericEvent(Object source, Clock clock) {
super(source, clock);
}
}
事件实现类
public class OrderEvent extends AbstractGenericEvent<OrderModel> {
public OrderEvent(OrderModel source) {
super(source);
}
}
事件监听器类,实现ApplicationListener 接口
@Component
public class OrderEventListener implements ApplicationListener<OrderEvent> {
@Override
public void onApplicationEvent(OrderEvent event) {
//
System.out.println(Thread.currentThread().getName() + "-receive msg: " + JSON.toJSONString(event.getSource()));
}
}
@Component
public class EmailEventListener implements ApplicationListener<OrderEvent> {
@Override
public void onApplicationEvent(OrderEvent event) {
//
System.out.println(Thread.currentThread().getName() + "-send email: " + JSON.toJSONString(event.getSource()));
}
}
测试
@GetMapping("hello")
public Object hello() {
OrderModel orderModel = new OrderModel();
orderModel.setId("1");
orderModel.setName("caocao");
// 发布Spring事件通知
SpringBeanUtil.getApplicationContext().publishEvent(new OrderEvent(orderModel));
System.out.println(Thread.currentThread().getName() + "-publish: ");
return "hello";
}
结果如下
从结果发现,无论是发布事件,还是监听事件使用了同一个线程,spring框架的事件机制默认是同步堵塞的,要想实现异步调用,需手动创建一个配置类,并设置线程池,如下
@Component
public class SpringConfiguration {
@Bean
public SimpleApplicationEventMulticaster applicationEventMulticaster(@Qualifier("defaultThreadPoolExecutor") ThreadPoolExecutor defaultThreadPoolExecutor) {
SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new SimpleApplicationEventMulticaster();
simpleApplicationEventMulticaster.setTaskExecutor(defaultThreadPoolExecutor);
return simpleApplicationEventMulticaster;
}
}
结果如下
从结果发现,发布和监听由不同的线程执行。
那SimpleApplicationEventMulticaster 实例化和系统默认的实例化加载顺序如如何?
在spring源码中,处理逻辑在 AbstractApplicationContext的initApplicationEventMulticaster 方法中,通过 beanFactory 查找是否有自定义的 Bean,如果没有,容器会自己 new 一个 SimpleApplicationEventMulticaster 对象注入到容器中。
还需继续分析spring中应用的设计模式及底层原理。