Spring中的观察者模式

一、Spring中观察者模式的四个角色
1.事件(ApplicationEvent)
ApplicationEvent 是所有事件对象的父类。ApplicationEvent 继承自 jdk 的 EventObject, 所有的事件都需要继承 ApplicationEvent, 并且通过source得到事件源。
下列描述了Spring提供的内置事件:
  • ContextRefreshedEvent:事件发布在 ApplicationContext 初始化或刷新时(例如:通过在 ConfigurableApplicationContext 接口使用refresh()方法)。这里,“初始化”意味着所有 bean 加载,post-processor bean 被检测到并且激活,单例预先实例化,ApplicationContext 对象可以使用了。只要上下文没有关闭,可以触发多次刷新, ApplicationContext 提供了一种可选择的支持这种“热”刷新。例如:XmlWebApplicationContext 支持热刷新,但 GenericApplicationContext 并非如此。具体是在 AbstractApplicationContext 的 finishRefresh() 方法中。
  • ContextStartedEvent:事件发布在 ApplicationContext 开始使用 ConfigurableApplicationContext 接口 start() 方法。这里,“开始”意味着所有生命周期 bean 接收到一个明确的起始信号。通常,这个信号用于明确停止后重新启动,但它也可以用于启动组件没有被配置为自动运行(例如:组件还没有开始初始化)。
  • ContextStoppedEvent:事件发布在 ApplicationContext 停止时通过使用 ConfigurableApplicationContext 接口上的 stop() 方法。在这里,“停止”意味着所有生命周期bean接收一个显式的停止信号。停止上下文可以通过重新调用start()方法。
  • ContextClosedEvent:事件发布在 ApplicationContext 关闭时通过关闭 ConfigurableApplicationContext 接口()方法。这里,“封闭”意味着所有单例 bean 被摧毁。一个封闭的环境达到生命的终结。它不能刷新或重启。
  • RequestHandledEvent:一个特定的web事件告诉所有能处理HTTP请求的bean 。这个事件是在请求完成后发布的。这个事件只适用于使用 Spring 的 DispatcherServlet 的web应用程序。
2.事件监听(ApplicationListener)
ApplicationListener 事件监听器,也就是观察者。继承自 jdk 的 EventListener,该类中只有一个方法 onApplicationEvent。当监听的事件发生后该方法会被执行。
3.事件发布(ApplicationContext)
ApplicationContext 是 Spring 中的核心容器,在事件监听中 ApplicationContext 可以作为事件的发布者,也就是事件源。因为 ApplicationContext 继承自 ApplicationEventPublisher。在 ApplicationEventPublisher 中定义了事件发布的方法 — publishEvent(Object event)
4.事件管理(ApplicationEventMulticaster)
ApplicationEventMulticaster 用于事件监听器的注册和事件的广播。监听器的注册就是通过它来实现的,它的作用是把 Applicationcontext 发布的 Event 广播给它的监听器列表。
二、Spring中实现观察者模式
  • 自定义需要发布的事件类,需要继承 ApplicationEvent 类或 PayloadApplicationEvent (该类也仅仅是对 ApplicationEvent 的一层封装)
  • 使用 @EventListener 来监听事件或者实现 ApplicationListener 接口。
  • 使用 ApplicationEventPublisher 来发布自定义事件(@Autowired注入即可)
@TransactionalEventListener 监听器:如果事件的发布不是在事务(@Transactional)范围内,则监听不到该事件,除非将 fallbackExecution 标志设置为 true(@TransactionalEventListener(fallbackExecution = true));如果在事务中,可以选择在事务的哪个阶段来监听事件,默认在事务提交后监听(@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION))。
以上介绍的事件监听都是同步,如果需要开启异步支持的话:
[AppleScript]  纯文本查看  复制代码
?
1
2
3
4
5
6
7
8
@Configuration
@EnableAsync
public class AsyncEventConfiguration implements AsyncConfigurer {
     @Override
     public Executor getAsyncExecutor ( ) {
         return Executors.newCachedThreadPool ( ) ;
     }
}
三、 实战
事件(MyEvent.java)
[AppleScript]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
@Component
public class MyEvent extends ApplicationEvent {
 
 
     public MyEvent ( ApplicationContext source ) {
         super ( source ) ;
         System.out.println ( "MyEvent 构造器执行" ) ;
     }
 
     public void echo ( ) {
         System.out.println ( "模拟业务逻辑执行" ) ;
     }
}

事件监听(MyListenerA.java、MyListenerB.java)
[AppleScript]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
@Component
public class MyListenerA implements ApplicationListener < MyEvent > {
 
 
     @Override
     public void onApplicationEvent ( MyEvent myEvent ) {
         System.out.println ( "MyListenerA" ) ;
         myEvent.echo ( ) ;
     }
}
 
[AppleScript]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
@Component
public class MyListenerB {
     
     @EventListener
     public void onApplicationEvent ( MyEvent myEvent ) {
         System.out.println ( "MyListenerB" ) ;
         myEvent.echo ( ) ;
     }
     
}

事件发布(MyPublisher.java)
[AppleScript]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
@Component
public class MyPublisher implements ApplicationContextAware {
 
     private ApplicationContext applicationContext;
 
 
     @Override
     public void setApplicationContext ( ApplicationContext applicationContext ) throws BeansException {
         this.applicationContext = applicationContext;
     }
 
     / * *
      * 发布事件
      * 监听该事件的监听者都可以获取消息
      *
      * @param myEvent
      * /
     public void publisherEvent ( MyEvent myEvent ) {
         System.out.println ( "---开始发布 myEvent 事件---" ) ;
         applicationContext.publishEvent ( myEvent ) ;
     }
}

单元测试
[AppleScript]  纯文本查看  复制代码
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
@RunWith ( SpringRunner. class )
@SpringBootTest
public class DesignPatternsApplicationTests {
 
     @Autowired
     private MyPublisher myPublisher;
     @Autowired
     private MyEvent myEvent;
 
     @Test
     public void contextLoads ( ) {
         myPublisher.publisherEvent ( myEvent ) ;
     }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值