这次终于把Spring的监听器讲明白了

简介: 监听器可以在使用过程时监听某些事件的发生,然后对这些事件做出响应处理。监听器对应用场景很多,用户的每一个操作都可以被定义为一个事件,通过监听器就能对某些业务场景中的事件进行监听。Spring中提供了ApplicationListener监听事件,本文会从应用出发讲解Spring的监听器,并逐步深入到源码之中。

听说微信搜索《Java鱼仔》会变更强哦!


本文收录于githubgitee ,里面有我完整的Java系列文章,学习或面试都可以看看哦


(一)Spring中的监听器


监听器可以在使用过程时监听某些事件的发生,然后对这些事件做出响应处理。监听器对应用场景很多,用户的每一个操作都可以被定义为一个事件,通过监听器就能对某些业务场景中的事件进行监听。


Spring中提供了ApplicationListener监听事件,本文会从应用出发讲解Spring的监听器,并逐步深入到源码之中。


(二)监听器的使用


首先自定义一个事件,只需要继承 ApplicationEvent 就可以创建一个自己的事件。


publicclassMyApplicationEventextendsApplicationEvent {
publicMyApplicationEvent(Objectsource) {
super(source);
    }
}

接着定义一个事件监听器,实现当监听到事件后在控制台输出一条消息。

@ComponentpublicclassMyListenerimplementsApplicationListener<MyApplicationEvent> {
@OverridepublicvoidonApplicationEvent(MyApplicationEventapplicationEvent) {
System.out.println("事件:"+applicationEvent.toString());
    }
}

在配置类中增加包扫描地址。

@Configuration@ComponentScan(basePackages="com.javayz.listenerDemo")
publicclassMainConfig {
}

网络异常,图片无法展示
|


通过结果可以发现,除了自定义的事件之外,还有一条Spring自带的事件也被打印出来,修改监听器,只打印自定义的事件:

@ComponentpublicclassMyListenerimplementsApplicationListener<ApplicationEvent> {
@OverridepublicvoidonApplicationEvent(ApplicationEventapplicationEvent) {
if (applicationEventinstanceofMyApplicationEvent){
System.out.println("事件:"+applicationEvent.toString());
        }
    }
}

(三)监听器源码分析:


通过 AnnotationConfigApplicationContext 进入Spring源码内部:

publicAnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
   }

这三个方法是Spring源码的核心,和监听器相关的内容在refresh方法中。进入refresh方法,和监听器相关的三个方法是initApplicationEventMulticaster()、registerListeners()和finishRefresh();


网络异常,图片无法展示
|


首先看initApplicationEventMulticaster()


protectedvoidinitApplicationEventMulticaster() {
ConfigurableListableBeanFactorybeanFactory=getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster=beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster ["+this.applicationEventMulticaster+"]");
         }
      }
else {
this.applicationEventMulticaster=newSimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '"+APPLICATION_EVENT_MULTICASTER_BEAN_NAME+"' bean, using "+"["+this.applicationEventMulticaster.getClass().getSimpleName() +"]");
         }
      }
   }

这一段代码很好理解,首先获取ConfigurableListableBeanFactory工厂,然后判断现在Bean工厂里是否有applicationEventMulticaster,如果有的话就获取该多播器,如果没有就新建一个SimpleApplicationEventMulticaster简单多播器并注册到Bean工厂中,这段代码相当于初始化一个多播器。


接下来是registerListeners()方法:


protectedvoidregisterListeners() {
// Register statically specified listeners first.for (ApplicationListener<?>listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
      }
// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let post-processors apply to them!String[] listenerBeanNames=getBeanNamesForType(ApplicationListener.class, true, false);
for (StringlistenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
      }
// Publish early application events now that we finally have a multicaster...Set<ApplicationEvent>earlyEventsToProcess=this.earlyApplicationEvents;
this.earlyApplicationEvents=null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEventearlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
         }
      }
   }

上面这段注册监听器的代码一共做了三件事情,第一件事情是容器中已有的监听器注册到多播器中;第二件事情是将Bean定义中的事件,也就是我们自己定义的监听器注册到多播器中;第三件事情是发布早期待处理事件,这些早期事件我们定义的监听器是监听不了的,这里发布早期待处理事件时通过multicastEvent()方法进行发布,这个方法会和下面一起讲。


最后看finishRefresh方法,该方法调用的publishEvent方法正式将我们定义的事件发布出去。



protectedvoidfinishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).clearResourceCaches();
// Initialize lifecycle processor for this context.initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.getLifecycleProcessor().onRefresh();
// Publish the final event.publishEvent(newContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.if (!NativeDetector.inNativeImage()) {
LiveBeansView.registerApplicationContext(this);
   }
}

进入publishEvent方法内部,可以看到它的内部同样调用了multicastEvent()方法,说明所有的真正发布动作都是由multicastEvent()完成的。


网络异常,图片无法展示
|


因此我们有必要来看一下multicastEvent()的发布过程,这里的代码也通俗易懂,判断是否有Executor,如果有的话异步加载invokeListener方法,没有的话同步调用invokeListener方法


publicvoidmulticastEvent(finalApplicationEventevent, @NullableResolvableTypeeventType) {
ResolvableTypetype= (eventType!=null?eventType : resolveDefaultEventType(event));
Executorexecutor=getTaskExecutor();
for (ApplicationListener<?>listener : getApplicationListeners(event, type)) {
if (executor!=null) {
executor.execute(() ->invokeListener(listener, event));
      }
else {
invokeListener(listener, event);
      }
   }
}

在invokeListener()方法中,终于看到了熟悉的onApplicationEvent方法,这个方法就是我们在自定义监听器时重写的方法,也正是在这里监听器调用了我们自己定义的onApplicationEvent(),实现了自定义的一些功能。


网络异常,图片无法展示
|


(四)总结


通过代码的实践以及源码的解读,监听的原理其实已经很明朗了,Spring的监听器源码可以算是观察者模式的最佳实践,我建议你照着本文的逻辑看一遍监听器源码,肯定会有新的收获。



相关文章
|
Web App开发 监控 Java
|
9月前
|
Java 数据安全/隐私保护 微服务
微服务——SpringBoot使用归纳——Spring Boot中使用监听器——Spring Boot中自定义事件监听
本文介绍了在Spring Boot中实现自定义事件监听的完整流程。首先通过继承`ApplicationEvent`创建自定义事件,例如包含用户数据的`MyEvent`。接着,实现`ApplicationListener`接口构建监听器,用于捕获并处理事件。最后,在服务层通过`ApplicationContext`发布事件,触发监听器执行相应逻辑。文章结合微服务场景,展示了如何在微服务A处理完逻辑后通知微服务B,具有很强的实战意义。
516 0
|
9月前
|
缓存 Java 数据库
微服务——SpringBoot使用归纳——Spring Boot中使用监听器——监听器介绍和使用
本文介绍了在Spring Boot中使用监听器的方法。首先讲解了Web监听器的概念,即通过监听特定事件(如ServletContext、HttpSession和ServletRequest的创建与销毁)实现监控和处理逻辑。接着详细说明了三种实际应用场景:1) 监听Servlet上下文对象以初始化缓存数据;2) 监听HTTP会话Session对象统计在线用户数;3) 监听客户端请求的Servlet Request对象获取访问信息。每种场景均配有代码示例,帮助开发者理解并应用监听器功能。
588 0
|
5月前
|
人工智能 安全 Java
Spring Boot 过滤器 拦截器 监听器
本文介绍了Spring Boot中的过滤器、拦截器和监听器的实现与应用。通过Filter接口和FilterRegistrationBean类,开发者可实现对请求和响应的数据过滤;使用HandlerInterceptor接口,可在控制器方法执行前后进行处理;利用各种监听器接口(如ServletRequestListener、HttpSessionListener等),可监听Web应用中的事件并作出响应。文章还提供了多个代码示例,帮助读者理解如何创建和配置这些组件,适用于构建更高效、安全和可控的Spring Boot应用程序。
639 0
|
11月前
|
Java Spring
Java Spring Boot监听事件和处理事件
通过上述步骤,我们可以在Java Spring Boot应用中实现事件的发布和监听。事件驱动模型可以帮助我们实现组件间的松耦合,提升系统的可维护性和可扩展性。无论是处理业务逻辑还是系统事件,Spring Boot的事件机制都提供了强大的支持和灵活性。希望本文能为您的开发工作提供实用的指导和帮助。
427 15
|
缓存 安全 Java
Spring高手之路26——全方位掌握事务监听器
本文深入探讨了Spring事务监听器的设计与实现,包括通过TransactionSynchronization接口和@TransactionalEventListener注解实现事务监听器的方法,并通过实例详细展示了如何在事务生命周期的不同阶段执行自定义逻辑,提供了实际应用场景中的最佳实践。
474 3
Spring高手之路26——全方位掌握事务监听器
|
NoSQL Java Redis
Spring Boot 监听 Redis Key 失效事件实现定时任务
Spring Boot 监听 Redis Key 失效事件实现定时任务
330 0
|
设计模式 Java Spring
Spring Boot监听器的底层实现原理
Spring Boot监听器的底层实现原理主要基于观察者模式(也称为发布-订阅模式),这是设计模式中用于实现对象之间一对多依赖的一种常见方式。在Spring Boot中,监听器的实现依赖于Spring框架提供的事件监听机制。
356 1
|
缓存 Java 数据库
Spring Boot中使用监听器
系统的介绍了监听器原理,以及在 Spring Boot 中如何使用监听器,列举了监听器的三个常用的案例,有很好的实战意义。最后讲解了项目中如何自定义事件和监听器,并结合微服务中常见的场景,给出具体的代码模型,均能运用到实际项目中去,希望读者认真消化。

热门文章

最新文章