spring event

Spring监听器

前言

代码耦合度不能太高,所以我们要尽量的将代码解耦,提到解耦,我们会想到使用消息队列来解耦,不过使用消息队列的话成本比较大。

我们也可以使用观察者模式来进行解耦,观察者模式就是发布订阅模式,Spring Event就是观察者模式,只是我们如果直接去写观察者模式,那么需要考虑很多东西,所以使用Spring Event便是一个不错的选择。

spring事件的原理 - 观察者模式

观察者设计模式 - 发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

​ Spring的事件监听有三个组成部分:

1. 事件(ApplicationEvent):监听器监听的事情。
2. 监听器(ApplicationListener): 观察者模式中的观察者, 监听器监听特定事件。
3. 事件发布器(ApplicationEventMulticaster):对外提供发布事件和增删事件监听器的接口。

目标:

  1. 监听器如何使用
  2. 监听器的类型
  3. 监听器的原理
  4. 调用事件
  5. 问题
1.事件多播器的作用?
2.注解方式、接口方式 两者的监听器注册在一起吗?
3.mq用的是什么设计模式?spring事件和mq的适用面?

1.监听器如何使用在这里插入图片描述

2.监听器的类型

2.1 内置监听器 - ApplicationContextEvent

实现 ApplicationContextEvent 的类就是内置的监听器,见名知意。
在这里插入图片描述

2.2 自定义监听器

类型一:基于接口 - ApplicationListener.class

在这里插入图片描述

类型二:基于注解 - @EventListener
在这里插入图片描述

3.监听器的原理

3.1 监听器的声明,调用,都是在 refresh() 方法里面进行的。

在这里插入图片描述
在这里插入图片描述

refresh()方法是spring的核心方法,其中完成了容器的初始化、Bean的生命周期也是从这里开始的。下面简单介绍一下refresh()方法中与监听器牵扯比较深的几个方法:

prepareRefresh() - 初始化上下文环境
创建事件监听器集合和事件集合
initApplicationEventMulticaster() - 创建事件多播器
事件多播器管理所有的事件监听器. 并广播事件给对应的监听器。
首先判断有没有事件多播器( applicationEventMulticaster ),如果有就直接加入容器中,如果没有就创建一个新的事件多播器并加入到容器中。
进入事件多播器看一下(ApplicationEventMulticaster.class)里面的方法都是些什么作用。
registerListeners() - 注册接口方式的监听器。如果OrderEventListenter采用的是接口方式, 那么就可以拿到. 因为它实现了ApplicationListener.拿到了, 就把监听器注册到多播器上.如果是注解方式, 不在这里注册。

在AnnotationConfigUtils.registerAnnotationConfigProcessors(xx,xx)里注册了BeanDefinition 对应的EventListenerMethodProcessor对象 , 而AnnotationConfigUtils是在AnnotationConfigServletWebServerApplicationContext构造方法里被加载。这里要提一下AnnotationConfigServletWebServerApplicationContext,他是spring boot启动入口的重要类(我这里用的是spring boot所以是这个类),可以相当于以前用xml的ClassPathXmlApplicationContext。

finishRefresh() - 发布
发布ContextRefreshedEvent()事件,表示容器都启动完成。

4.调用事件

4.1 publishEvent() 具体实现

在这里插入图片描述

这里具体做了3件事:
1.获取事件
2.广播事件
3.广播事件给父类的监听器

4.2 multicastEvent() 具体实现

在这里插入图片描述

根据线程池是否为空判断进行同步调用还是异步调用,默认同步调用。

4.3 调用事件的两种形式 - 同步、异步

默认同步调用,根据代码逻辑
在这里插入图片描述

当需要异步调用时需要指定 taskExecutor,代码如下:

    @Bean(name = "applicationEventMulticaster")
    public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
        SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster();

        // 这里指定了 taskExecutor, 就会使用异步的方式去执行
        eventMulticaster.setTaskExecutor(new SimpleAsyncTaskExecutor());
        return eventMulticaster;
    }

4.4 广播事件 - doInvokeListener(ApplicationListener listener, ApplicationEvent event)

最终调用的是监听器的onApplicationEvent方法. 这个方法就是每一个监听器都会自定义的方法,具体执行的就是我们自定义监听器的onApplicationEvent()方法中的逻辑

5.问题

1.事件多播器的作用?
	事件多播器管理所有的事件监听器. 并广播事件给对应的监听器。
2.注解方式、接口方式 两者的监听器注册在一起吗?
	不在一起。接口方式是在refresh()方法里面注册,注解方式是在另外一个类加载。
3.mq用的是什么设计模式?spring事件和mq的适用面?
	mq用的也是观察者设计模式。分布式的微服务中,子服务与子服务之间的通信可以选择成熟的MQ中间件来做到业务的解耦;单个子服务,不同的模块中通信使用spring事件。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值