Spring事件监听ApplicationListener源码流程分析
spring的事件机制是基于观察者设计模式的,ApplicationListener#onApplicationEvent(Event)方法,用于对事件的处理 。在容器初始化的时候执行注册到容器中的Listener。逆向来查看执行过程
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
SimpleApplicationEventMulticaster#multicastEvent执行调用所有实现了ApplicationListener接口的Bean.
/*
*广播所有注册监听的事件
*设置个Excutor可以异步执行
*/
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
private Executor taskExecutor;//可以异步执行listener
......
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void multicastEvent(final ApplicationEvent event) {
//遍历执行listener,getApplicationListeners调用AbstractApplicationEventMulticaster父类方法
for (final ApplicationListener listener : getApplicationListeners(event)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
listener.onApplicationEvent(event);
}
});
}
else {
listener.onApplicationEvent(event);
}
}
}
}
父类AbstractApplicationEventMulticaster#getApplicationListeners()部分源码:
/*
*抽象AbstractApplicationEventMulticaster 事件广播者
*/
public abstract class AbstractApplicationEventMulticaster
implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
.....
//实现此BeanFactoryAware接口,初始化时,将会将beanFactory注入到该实例中。便于后续获取bean
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
if (this.beanClassLoader == null && beanFactory instanceof ConfigurableBeanFactory) {
this.beanClassLoader = ((ConfigurableBeanFactory) beanFactory).getBeanClassLoader();
}
}
......
/*
*获取容器监听
*/
protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event) {
Class<? extends ApplicationEvent> eventType = event.getClass();
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
else {
retriever = new ListenerRetriever(true);
LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>();
Set<ApplicationListener<?>> listeners;
Set<String> listenerBeans;
synchronized (this.defaultRetriever) {
listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
}
for (ApplicationListener<?> listener : listeners) {
if (supportsEvent(listener, eventType, sourceType)) {
retriever.applicationListeners.add(listener);
allListeners.add(listener);
}
}
if (!listenerBeans.isEmpty()) {
BeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : listenerBeans) {
try {
Class<?> listenerType = beanFactory.getType(listenerBeanName);
if (listenerType == null || supportsEvent(listenerType, event)) {
ApplicationListener<?> listener =
beanFactory.getBean(listenerBeanName, ApplicationListener.class);
if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
retriever.applicationListenerBeans.add(listenerBeanName);
allListeners.add(listener);
}
}
}
catch (NoSuchBeanDefinitionException ex) {
// Singleton listener instance (without backing bean definition) disappeared -
// probably in the middle of the destruction phase
}
}
}
//对监听排序
OrderComparator.sort(allListeners);
if (this.beanClassLoader == null ||
(ClassUtils.isCacheSafe(eventType, this.beanClassLoader) &&
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
this.retrieverCache.put(cacheKey, retriever);
}
return allListeners;
}
}
....
}
AbstractApplicationContext#publishEvent()调用发布事件源码
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean{
......
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
......
/**
* 初始化事件广播器,如果未配置,默认使用SimpleApplicationEventMulticaster
*这个何时执行?稍后将会贴出代码
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
......
//获取容器事件广播器
ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
if (this.applicationEventMulticaster == null) {
throw new IllegalStateException("ApplicationEventMulticaster not initialized - " + "call 'refresh' before multicasting events via the context: " + this);
}
return this.applicationEventMulticaster;
}
......
@Override
public void publishEvent(ApplicationEvent event) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
//获取到事件广播器,发布事件
getApplicationEventMulticaster().multicastEvent(event);
//如果存在父容器,父容器也将发布事件
if (this.parent != null) {
this.parent.publishEvent(event);
}
}
......
}
AbstractApplicationContext#finishRefresh()源码
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean{
......
protected void finishRefresh() {
// Initialize lifecycle processor for this context.
initLifecycleProcessor(); // Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh(); // Publish the final event. 发布事件
publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
......
}
AbstractApplicationContext#refresh()源码
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean{
.....
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh(); // Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory); try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.
initMessageSource(); // Initialize event multicaster for this context.初始化事件广播器,如果未配置,默认使用SimpleApplicationEventMulticaster
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
onRefresh(); // Check for listener beans and register them.
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.完成refresh
finishRefresh();
} catch (BeansException ex) {
logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex); // Destroy already created singletons to avoid dangling resources.
destroyBeans(); // Reset 'active' flag.
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
}
}
}
.....
}
spring容器启动将会执行到AbstractApplicationContext#refresh()。由此可以看到spring事件的流程,在关注的地方都加了注释。我们看代码不要挨着看,观其大意。看自己需要的就行。
下面写了一个demo看看,如何实现事件的异步。
/**
* @Auther: lanwei
* @Date: 2018/11/1 23:38
* @Description:
*/
public class ApplicationListenerAsynTest {
public static void main(String[] args) {
final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.addApplicationListener(new ApplicationListener<ApplicationEvent>() {
@Override
public void onApplicationEvent(ApplicationEvent event) {
println(event.getSource().toString());
}
});
context.register(MyConfiguration.class);
context.refresh();
context.close();
} @Configuration
public static class MyConfiguration { @Bean
public SimpleApplicationEventMulticaster applicationEventMulticaster() {
SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
multicaster.setTaskExecutor(new ThreadPoolExecutor(5, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10)));
return multicaster;
}
} private static void println(String message) {
System.out.printf("[线程 : %s] %s\n",
Thread.currentThread().getName(), // 当前线程名称
message);
}
}
Spring事件监听ApplicationListener源码流程分析的更多相关文章
- Spring事件监听机制源码解析
Spring事件监听器使用 1.Spring事件监听体系包括三个组件:事件.事件监听器,事件广播器. 事件:定义事件类型和事件源,需要继承ApplicationEvent. package com.y ...
- SpringBoot事件监听机制源码分析(上) SpringBoot源码(九)
SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringApplicat ...
- Spring事件监听Demo
Spring事件监听实现了观察者模式.本Demo在junit4测试环境中实现 主要有三个类事件类.监听器类.事件发布类(入口) 事件类必须继承 ApplicationEvent,代码如下: impor ...
- Flask源码流程分析(一)
Flask源码流程分析: 1.项目启动: 1.实例化Flask对象 1. 重要的加载项: * url_rule_class = Rule * url_map_class = Map * session ...
- 【spring源码学习】spring的事件发布监听机制源码解析
[一]相关源代码类 (1)spring的事件发布监听机制的核心管理类:org.springframework.context.event.SimpleApplicationEventMulticast ...
- Spring的事件监听ApplicationListener
ApplicationListener是Spring事件机制的一部分,与抽象类ApplicationEvent类配合来完成ApplicationContext的事件机制. 如果容器中存在Applica ...
- Spring 事件监听机制及原理分析
简介 在JAVA体系中,有支持实现事件监听机制,在Spring 中也专门提供了一套事件机制的接口,方便我们实现.比如我们可以实现当用户注册后,给他发送一封邮件告诉他注册成功的一些信息,比如用户订阅的主 ...
- spring事件监听(eventListener)
原理:观察者模式 spring的事件监听有三个部分组成,事件(ApplicationEvent).监听器(ApplicationListener)和事件发布操作. 事件 事件类需要继承Applicat ...
- 一文读懂Spring动态配置多数据源---源码详细分析
Spring动态多数据源源码分析及解读 一.为什么要研究Spring动态多数据源 期初,最开始的原因是:想将答题服务中发送主观题答题数据给批改中间件这块抽象出来, 但这块主要使用的是mq消息的方式 ...
随机推荐
- SQLException: #22001你知道这个错误码吗
做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! java.sql.SQLException: #22001 java.sql.SQLException: #22001 a ...
- 转载:PHP扩展函数库-文件系统、进程与网络
PHP的扩展函数库十分庞大,官方的非官方的,在这里只记录一些目前比较常用的扩展,对于这一部分,也只是记录其中一些核心的函数,不是一个全面记录.对于详细的扩展函数说明,需要在使用中参考PHP的用户手册. ...
- 禁止Steam VR随着虚幻4自动启动
1.禁止启动UE4的时候启动修改这个文件Program Files\Epic Games\XXXX\Engine\Plugins\Runtime\Steam\SteamVR\SteamVR.uplug ...
- python 修改、读取图片元数据
图片元数据 图片元数据(metadata)是嵌入到图片文件中的一些标签.比较像文件属性,但是种类繁多.常见的几种标准有: EXIF:通常被数码相机在拍摄照片时自动添加,比如相机型号.镜头.曝光.图片尺 ...
- Spring cloud实战——服务提供者
目录讲解: 一.服务提供者与服务消费者的概念 二.编写一个服务提供者的测试类(code) 1.1. 使用微服务构建的是分布式系统,微服务之间通过网络进行通信.我们使用微服务提供者与服务消费者来描述微服 ...
- Shell中比较判断
一.shell判断数组中是否包含某个元素:ary=(1 2 3)a=2if [[ "${ary[@]}" =~ "$a" ]] ; then echo & ...
- Mysql系列-性能优化神器EXPLAIN使用介绍及分析
MySQL 提供了一个 EXPLAIN 命令, 它可以对 SELECT 语句进行分析, 并输出 SELECT 执行的详细信息, 以供开发人员针对性优化. EXPLAIN 命令用法十分简单, 在 SEL ...
- shell数组处理
linux shell在编程方面比windows 批处理强大太多,无论是在循环.运算.已经数据类型方面都是不能比较的. 下面是个人在使用时候,对它在数组方面一些操作进行的总结. 1.数组定义 ...
- Delphi 声明特性
- 《设计模式之美》 <02>评判代码质量好坏的维度
如何评价代码质量的高低? 实际上,咱们平时嘴中常说的“好”和“烂”,是对代码质量的一种描述.“好”笼统地表示代码质量高,“烂”笼统地表示代码质量低.对于代码质量的描述,除了“好”“烂”这样比较简单粗暴 ...