在对象之间定义了一对多的依赖,这样一来,一个对象的状态改变了,依赖它的对象会收到通知并自动更新。其实就是发布订阅模式,发布者发布消息,订阅者订阅消息。订阅了就能收到消息,没订阅就收不到消息。
观察者模式还有其他的一些称谓,比如: 发布-订阅模式,模型-视图模式,源-监听器模式,从属模式。其实都是说的是一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个对象在状态发生变化时,会通知所有观察者对象,使它们自动的更新自己。
Subject被观察者
定义被观察者必须实行的职责,必须具有动态的增加、删除观察者。它一般是抽象类或实现类,仅仅是完成被观察者必须实现的职责: 管理观察者并通知观察者。
Observer观察者
观察者接收到消息后,进行update更新操作,对接收到的信息进行处理。
ConcreteSubject具体的被观察者
定义被观察者的具体业务逻辑,同时定义哪些事件进行通知
ConcreteObserver具体的观察者
每个观察者接收到信息后的处理反应是不同的,各个观察者有各自的处理逻辑。
具体的类图结构:
Suject被观察者接口
public interface Subject {
void add(Observer observer);
void remove(Observer observer);
void notifyObserver();
}
Observer观察者
public interface Observer<T> {
void update(T t);
}
ConcreteSubject具体的被观察者
public class OrderSuject implements Subject {
private List<Observer> observerList = Collections.synchronizedList(new ArrayList<>());
private String message;
public OrderSuject(String message) {
this.message = message;
}
@Override
public void add(Observer observer) {
observerList.add(observer);
}
@Override
public void remove(Observer observer) {
observerList.remove(observer);
}
@Override
public void notifyObserver() {
observerList.forEach(observer -> observer.update(message));
}
}
ConcreteObserver具体的观察者
public class SmsObserver implements Observer<String>{
@Override
public void update(String s) {
System.out.println("发送短信:"+s);
}
}
public class EmailObserver implements Observer<String>{
@Override
public void update(String s) {
System.out.println("发送邮件:"+s);
}
}
测试类
public class ObserverTest {
public static void main(String[] args) {
OrderSuject orderSuject=new OrderSuject("订单创建成功了");
orderSuject.add(new SmsObserver());
orderSuject.add(new EmailObserver());
orderSuject.notifyObserver();
}
}
//运行结果为:
//发送短信:订单创建成功了
//发送邮件:订单创建成功了
jdk内置了观察者接口java.util.Observer,主题被观察者 java.util.Observable。观察者实现Observer接口,被观察者继承Observable类。
观察者
public class SmsObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("jdk用户下单成功,准备发送短信了:"+arg.toString());
}
}
public class EmailObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("jdk用户下单成功,准备发送邮件了:"+arg.toString());
}
}
被观察者
public class OrderObservable extends Observable {
@Override
public void notifyObservers(Object arg) {
setChanged();
super.notifyObservers(arg);
}
public static void main(String[] args) {
OrderObservable orderObservable=new OrderObservable();
orderObservable.addObserver(new EmailObserver());
orderObservable.addObserver(new SmsObserver());
orderObservable.notifyObservers("订单创建成功");
}
}
//运行结果:
//jdk用户下单成功,准备发送短信了:订单创建成功
//jdk用户下单成功,准备发送邮件了:订单创建成功
Spring的事件监听机制其实就是基于观察者模式来实现的。Spring实现监听机制有多种方式,具体如下:
监听事件: 实现ApplicationEvent 抽象类
监听者/观察者: 实现ApplicationListener接口,重写onApplicationEvent方法
发布事件: 通过 ApplicationEventPublisher接口的publishEvent方法发布事件 ,ApplicationContext继承了ApplicationEventPublisher接口。
具体代码实现如下:
//订单事件类
@Getter
@Setter
public class OrderEvent extends ApplicationEvent {
private Order order;
public OrderEvent(Object source,Order order) {
super(source);
this.order=order;
}
}
//短信监听类,监听事件OrderEvent
@Component
public class SmsListener implements ApplicationListener<OrderEvent> {
@Override
public void onApplicationEvent(OrderEvent event) {
Order order = Optional.ofNullable(event.getOrder()).orElseGet(Order::new);
System.out.println("订单创建成功了,准备发送短信了:"+order.getCode());
}
}
// 邮件监听类,监听事件OrderEvent
@Component
public class EmailListener implements ApplicationListener<OrderEvent> {
@Override
public void onApplicationEvent(OrderEvent event) {
Order order = Optional.ofNullable(event.getOrder()).orElseGet(Order::new);
System.out.println("订单创建成功了,准备发送邮件了,cod:"+order.getCode());
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ApiServerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ApiServerApplicationTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void testEvent(){
Order order=new Order();
order.setId(15L);
order.setCode("X15212541");
OrderEvent orderEvent = new OrderEvent(this, order);
applicationContext.publishEvent(orderEvent);
}
}
//输出结果:
//订单创建成功了,准备发送邮件了,cod:X15212541
//订单创建成功了,准备发送短信了:X15212541
除了实现ApplicationListener接口之外,Spring可以通过注解@EventListener注解实现监听类,具体如下:
//通过注解@EventListener代替ApplicationListener实现事件监听
@Component
public class TelListener {
@EventListener
public void onApplicationEvent(OrderEvent event){
System.out.println("我是注解驱动监听类,订单创建成了,code="+event.getOrder().getCode());
}
}
// 运行结果:
//我是注解驱动监听类,订单创建成功了,code=X15212541
//订单创建成功了,准备发送邮件了,cod:X15212541
//订单创建成功了,准备发送短信了:X15212541
@EventListener注解还可以通过配置condition条件来设置满足特定条件后,才执行该监听事件,支持SpringEL表达式
Spring支持同步和异步两种方式来执行监听事件,具体原理见 SimpleApplicationEventMulticaster类 :
如下代码可以看到,如果Executor 不为空就会采用异步方式执行,否则的话就是同步方式
@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
@Component
public class SmsListener implements ApplicationListener<OrderEvent> {
@Override
@Async
public void onApplicationEvent(OrderEvent event) {
Order order = Optional.ofNullable(event.getOrder()).orElseGet(Order::new);
System.out.println("线程ID="+Thread.currentThread().getId()+" | 订单创建成功了,准备发送短信了:"+order.getCode());
}
}
运行结果:
线程ID=1我是注解驱动监听类,订单创建成功了,code=X15212541
线程ID=1订单创建成功了,准备发送邮件了,cod:X15212541
线程ID=57 | 订单创建成功了,准备发送短信了:X15212541
@TransactionalEventListener
Spring提供了@TransactionalEventListener注解,它是@EventListener的一个扩展。允许将事件的监听器绑定到事务的一个阶段。具体的事务阶段包含以下4个:
public enum TransactionPhase {
BEFORE_COMMIT (默认),
AFTER_COMMIT,
AFTER_ROLLBACK,
AFTER_COMPLETION
}
需要注意的是,如果没有正在运行的事务,就不会触发该事件,除非设置fallbackExecution =true
@TransactionalEventListener(fallbackExecution = true)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。