Spring之观察者模式
基于SpringBoot2
1. 概念
观察者模式 (Observer Pattern)
:定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
观察者模式包含观察目标和观察者两类对象,一个目标可以有任意数目的与之相依赖的观察者,一旦观察目标的状态发生改变,所有的观察者都将得到通知
它也叫发布订阅模式(Publish/Subscibe)
它的好处就是解耦
,订阅者无需关心发布者做了什么,接收到通知做事就行了
在 MQ 或者 Redis 等中间件中也都有发布订阅的实现
2. 使用场景
说到观察者模式很多可能不太清楚,但是说发布订阅就很清晰
比如一个微信公众号,大佬发了一篇文章,关注他的人都会收到文章推送,这就是发布订阅
再如用户注册后给用户发送短信邮件通知,这是两个不同的业务,我们可以进行解耦
再如视频会员过期前给你推送消息提醒
在现实生活中观察者模式处处可见
3. Spring中观察者模式的四个角色
3.1 事件(ApplicationEvent)
ApplicationEvent 是所有事件对象的父类。ApplicationEvent 继承自 jdk 的 EventObject, 所有的事件都需要继承 ApplicationEvent, 并且通过 source 得到事件源
Spring 内置的四个事件,他们都是 ApplicationEvent 的子类,通过监听这四个组件我们可以在 ApplicationContext 启动刷新停止关闭时做一些操作
3.2 事件监听(ApplicationListener)
ApplicationListener 事件监听器,也就是观察者。继承自 jdk 的 EventListener,该类中只有一个方法 onApplicationEvent。当监听的事件发生后该方法会被执行。
3.3 事件发布(ApplicationContext)
ApplicationContext 是 Spring 中的核心容器,在事件监听中 ApplicationContext 可以作为事件的发布者,也就是事件源。因为 ApplicationContext 继承自 ApplicationEventPublisher。在 ApplicationEventPublisher 中定义了事件发布的方法 — publishEvent(Object event)
3.4 事件管理(ApplicationEventMulticaster)
ApplicationEventMulticaster 用于事件监听器的注册和事件的广播。监听器的注册就是通过它来实现的,它的作用是把 Applicationcontext 发布的 Event 广播给它的监听器列表‘
4. 使用
4.1 自定义事件
继承 ApplicationEvent 即可
1 |
|
4.2 事件发布
我们可以使用 ApplicationEventPublisher 来发布事件,或者使用 ApplicationContext 也可以
1 |
|
4.3 事件监听
4.3.1 实现 ApplicationListener 接口进行监听
当我们发布者发布事件时这边就会监听到 TaskEvent 事件
4.3.2 使用 @EventListener 注解进行监听
4.3.3 条件监听
在 @EventListener
注解中有三个值,value 和 classes 都是为了指定监听的事件,可以不用写,在方法参数指定,@AliasFor
顾名思义就是取别名,在 spring 中value是默认值,比如这样
1 |
|
这个时候我们就不知道 value 是干啥的了,取了别名后我们就能知道它是要监听的事件的 class
@AliasFor 标签使用限制:
- 互为别名的属性属性值类型,默认值,都是相同的,且必须设置默认值
- 为别名的注解必须成对出现,比如 value 属性添加了@AliasFor](“classes”),那么 path 属性就必须添加 @AliasFor(“value”);
condition 属性是设置监听条件,支持SpEL表达式[1]
监听 TaskEvent 事件,execution 为 true 时才调用方法
4.3.4 异步监听
配合 @Async
注解可以实现异步监听,不阻塞主线程,提高程序效率,使用 @Async
需要使用 @EnableAsync
注解来开启异步支持
不再需要声明事务,因为Spring中的事务默认是和线程绑定的,当新启动一条线程时,将开启另一个独立的事务
4.3.5 事务回调监听
在上面使用 @EventListener 对事件进行监听,这时候是和我们发布者业务在一个事务内的,拿用户注册来说,注册后发邮件给用户,我们写一个监听事件去发邮件,如果说发邮件后,代码出错了,那此时事务就会回滚,但是邮件已经发出去了,那不太合适
这时候就需要用到 @TransactionalEventListener 了,看名字就知道它是 @EventListener 的升级版!他可以配合事务,在不同的事务阶段去监听
我们可以看到它的增强属性,首先我们可以看下事务绑定的几个阶段,默认就是 TransactionPhase.AFTER_COMMIT
在我们上面的例子中我们需要在事务提交后给用户发送邮件,这个时候就派上用场了
再来看看 fallbackExecution 属性的作用,官方注释写的很明白,如果没有事务正在运行,是否应该处理事件,默认值为 false ,那就是不处理
5. 参考
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!