摘要:准备好了我们可以开始向中发布,当发布后,所有在中的都会收到对应的。将类注入到的中。测试和通过方法将发布到应用上下文中,同时这个动作会触发收到事件。深入剖析发布与监听的过程在使用方法发布的时候,最终会调用到中的类的如下的一段代码。
本篇主要来聊一聊spring中ApplicationListener接口和ApplicationEvent类。
从命名上可以很容易的看出来一个是listener另一个是被监听的事件,但是spring是如何做到listener去监听event?同时我们该如何在日常开发过程中使用spring为我们提供的这一个监听模式?
0x01 listener和event关系spring启动后会为我们创建好一个上下文,也即是我们经常听到的spring IOC的上下文ApplicationContext,可以理解ApplicationContext中是初始化了所有在.xml文件配置的bean标签的bean。
我们通过在.xml文件中定义一个listener的bean,这个listener用来监听event,listener通过实现方法com.boyu.budmw.test.AppListener#onApplicationEvent来对event进行处理。
listener准备好了我们可以开始向ApplicationContext中发布event,当event发布后,所有在ApplicationContext中的listener都会收到对应的event。
0x02 如何使用listener和event这一特性
定义event
首先我们要定义一个event,不然拿什么来触发?
public class AppEvent extends ApplicationEvent { public AppEvent(Object source) { super(source); } public void sayHi(){ System.out.println("sayHi"); } }
定义一个event非常简单,但是需要注意,这里一定要实现带有一个参数的构造函数,因为父类ApplicationEvent中没有默认的构造方法,所以子类必须重载构造函数。
定义listener
public class AppListener implements ApplicationListener { public void onApplicationEvent(ApplicationEvent event) { if(!(event instanceof AppEvent)){ return ; } AppEvent appEvent = (AppEvent)event; appEvent.sayHi(); } }
上面是一个listener的实现类,listener类必须实现ApplicationListener接口,同时要实现接口中的onApplicationEvent方法,这个方法会接收到一个event,然后可以对这个event进行处理了。
将listener类注入到spring的ApplicationContext中。
测试listener和event
public class ListenerTest { public static void main (String args[]){ ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/config/applicationContext.xml"); AppEvent appEvent = new AppEvent("appEvent"); applicationContext.publishEvent(appEvent); } }
通过org.springframework.context.ApplicationEventPublisher#publishEvent方法将event发布到spring应用上下文中,同时这个动作会触发listener收到event事件。
0x03 深入剖析发布与监听的过程在使用org.springframework.context.ApplicationEventPublisher#publishEvent方法发布event的时候,最终会调用到spring中的org.springframework.context.event.SimpleApplicationEventMulticaster类的如下的一段代码。
当然这也是取决于你有没有对applicationEventMulticaster进行定制,如果定制了,会走到你自己定制的逻辑,下面这段是spring默认的一段逻辑。
public void multicastEvent(final ApplicationEvent event) { for (final ApplicationListener listener : getApplicationListeners(event)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @SuppressWarnings("unchecked") public void run() { listener.onApplicationEvent(event); } }); } else { listener.onApplicationEvent(event); } } }
这段代码一看挺简单,通过org.springframework.context.event.AbstractApplicationEventMulticaster#getApplicationListeners(org.springframework.context.ApplicationEvent)这个方法获得applicationContext中所有的listener,然后依次调用各个listener。
getApplicationListeners这个方法中的逻辑是从beanFactory中获取所有的ApplicationListener对象。
0x04 这个特性有什么用?当然这里也只能谈谈自己认识到的应用场景,event中可以定义一些复杂的对象或者叫服务,这样服务提供者就和服务的使用者彻底解耦了。
根据自己的业务场景可以做很多事情,期待你的补充。
0x05 参考这篇我想最有参考价值的东西还是spring的源码,可以去调试相关的代码。spring有很多有价值或者说值得学习的设计思想,同样编码的规范也可以让你学到很多,多多跟着自己的思维去调试spring源码。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/66004.html
摘要:实体代码如下所示恒宇少年码云用户名密码创建内添加一个注册方法,该方法只是实现注册事件发布功能,代码如下所示恒宇少年码云用户注册方法省略其他逻辑发布事件事件发布是由对象管控的,我们发布事件前需要注入对象调用方法完成事件发布。 ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业务逻辑之...
摘要:前言由于之前使用事件机制出现了问题,所以特意去了解这块的源码。事件机制其实就是事件发布订阅注意在中订阅指的是监听。 前言 由于之前使用Spring事件机制出现了问题,所以特意去了解这块的源码。Spring事件机制其实就是事件发布/订阅(注意在Spring中订阅指的是监听)。 PS:Spring版本为5.1.5.RELEASE 源码分析 初始化 初始化这块关键是核心组件的注册 App...
摘要:背景是事件机制的一部分,与抽象类类配合来完成的事件机制。如果容器中存在的,当调用方法时,对应的会被触发。单元测试类执行单元测试,会发现事件发布之后,监听器方法被调用,日志被打印出来。 背景 ApplicationListener是Spring事件机制的一部分,与抽象类ApplicationEvent类配合来完成ApplicationContext的事件机制。 如果容器中存在Applic...
摘要:前言之前使用的事件机制来改造系统,完成了部分模块的解耦。但是实际使用时却发现存在以下问题当批量推送时,如果在处理的过程中抛出异常,则会导致后续的推送中断。但是实际上却是抛出异常会导致后续事件的推送中断。 前言 之前使用Spring的事件机制来改造系统,完成了部分模块的解耦。但是实际使用时却发现存在以下问题: 当ApplicationEventPublisher批量推送Applicati...
摘要:会一直完善下去,欢迎建议和指导,同时也欢迎中用到了那些设计模式中用到了那些设计模式这两个问题,在面试中比较常见。工厂设计模式使用工厂模式可以通过或创建对象。 我自己总结的Java学习的系统知识点以及面试问题,已经开源,目前已经 41k+ Star。会一直完善下去,欢迎建议和指导,同时也欢迎Star: https://github.com/Snailclimb... JDK 中用到了那...
阅读 3206·2021-11-11 16:55
阅读 2351·2021-10-13 09:39
阅读 2351·2021-09-13 10:27
阅读 2130·2019-08-30 15:55
阅读 3064·2019-08-30 15:54
阅读 3108·2019-08-29 16:34
阅读 1797·2019-08-29 12:41
阅读 1051·2019-08-29 11:33