spring--监听器(listener)原理解析

spring--监听器(listener)原理解析

文章目录

spring的监听器(listener)原理解析首先看一下如何使用listener源码解析-加载监听器initApplicationEventMulticaster();registerListeners();这里解释一下通过硬编码添加的监听器的意思

源码解析-发布(publishEvent)方法总结

spring的监听器(listener)原理解析

首先看一下如何使用listener

编写事件源(Event)

import org.springframework.context.ApplicationEvent;

public class TestEvent extends ApplicationEvent {

public TestEvent(Object obj) {

super(obj);

}

}

编写事件监听器(listener)

import org.springframework.context.ApplicationListener;

import org.springframework.stereotype.Component;

@Component

public class TestListener implements ApplicationListener {

@Override

public void onApplicationEvent(TestEvent testEvent) {

System.out.println(testEvent.getSource());

}

}

编写测试用例

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.test.context.SpringBootTest;

import org.springframework.context.ApplicationEventPublisher;

import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)

@SpringBootTest

public class ListenerTest {

@Autowired

private ApplicationEventPublisher applicationEventPublisher;

@Test

public void test() {

TestEvent testEvent = new TestEvent("hello word");

applicationEventPublisher.publishEvent(testEvent);

}

}

执行日志

. ____ _ __ _ _

/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \

( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \

\\/ ___)| |_)| | | | | || (_| | ) ) ) )

' |____| .__|_| |_|_| |_\__, | / / / /

=========|_|==============|___/=/_/_/_/

:: Spring Boot :: (v2.2.0.RELEASE)

2020-05-26 09:30:20.113 INFO 10760 --- [ main] com.example.demo.listener.ListenerTest : Starting ListenerTest on PC with PID 10760 (started by ASUS in E:\workspace\demo)

2020-05-26 09:30:20.115 INFO 10760 --- [ main] com.example.demo.listener.ListenerTest : No active profile set, falling back to default profiles: default

2020-05-26 09:30:20.568 INFO 10760 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!

2020-05-26 09:30:20.572 INFO 10760 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.

2020-05-26 09:30:20.613 INFO 10760 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 21ms. Found 0 repository interfaces.

2020-05-26 09:30:21.714 INFO 10760 --- [ main] com.example.demo.listener.ListenerTest : Started ListenerTest in 2.261 seconds (JVM running for 3.634)

hello word

Process finished with exit code 0

源码解析-加载监听器

这个是在创建applicationContext过程中,从抽象类AbstractApplicationContext的refresh方法开始,去除注释和日志,我们来看看源码

@Override

public void refresh() throws BeansException, IllegalStateException {

synchronized (this.startupShutdownMonitor) {

prepareRefresh();

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

prepareBeanFactory(beanFactory);

try {

postProcessBeanFactory(beanFactory);

invokeBeanFactoryPostProcessors(beanFactory);

registerBeanPostProcessors(beanFactory);

initMessageSource();

// 初始化一个广播器,之后注册监听器和发布事件都基于该广播器执行

initApplicationEventMulticaster();

onRefresh();

// 注册监听器到广播器中

registerListeners();

finishBeanFactoryInitialization(beanFactory);

finishRefresh();

} catch (BeansException ex) {

destroyBeans();

cancelRefresh(ex);

throw ex;

} finally {

resetCommonCaches();

}

}

}

这里我们只关心两个方法initApplicationEventMulticaster和registerListeners

initApplicationEventMulticaster(); protected void initApplicationEventMulticaster() {

// 获取bean工厂

ConfigurableListableBeanFactory beanFactory = getBeanFactory();

// 判断是否存在applicationEventMulticaster这个bean

if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {

// 如果存在则实例化这个bean并保存到applicationEventMulticaster

this.applicationEventMulticaster =

beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);

}

else {

// 否则创建一个广播器并注册单例到bean工厂

this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);

beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);

}

}

registerListeners(); protected void registerListeners() {

// Register statically specified listeners first--这是官方的注释,指通过硬编码添加的监听器

for (ApplicationListener listener : getApplicationListeners()) {

getApplicationEventMulticaster().addApplicationListener(listener);

}

// 从bean工厂获取所有实现了ApplicationListener接口的bean

String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);

for (String listenerBeanName : listenerBeanNames) {

getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

}

// 预处理方法(prepareRefresh)之后,注册监听器方法(registerListeners)之前,发布的广播/事件(publishEvent)的都会缓存在这里进行统一发布,相当于创建应用上下文时的延迟广播

// multicastEvent方法具体实现放在发布过程详解

Set earlyEventsToProcess = this.earlyApplicationEvents;

this.earlyApplicationEvents = null;

if (earlyEventsToProcess != null) {

for (ApplicationEvent earlyEvent : earlyEventsToProcess) {

getApplicationEventMulticaster().multicastEvent(earlyEvent);

}

}

}

添加监听器到applicationListeners和applicationListenerBeans集合

public final Set> applicationListeners = new LinkedHashSet<>();

@Override

public void addApplicationListener(ApplicationListener listener) {

synchronized (this.retrievalMutex) {

// 获取代理对象

Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);

// 避免重复添加监听器,主要防止代理类和被代理类同时处理一个事件

if (singletonTarget instanceof ApplicationListener) {

this.defaultRetriever.applicationListeners.remove(singletonTarget);

}

this.defaultRetriever.applicationListeners.add(listener);

// 由于在发布事件后会找到所有监听他的监听器并且缓存下来,所以当添加新的监听器时需要清空缓存,这样下次发布事件才能让新添加的监听器有机会处理事件

this.retrieverCache.clear();

}

}

public final Set applicationListenerBeans = new LinkedHashSet<>();

@Override

public void addApplicationListenerBean(String listenerBeanName) {

synchronized (this.retrievalMutex) {

this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);

this.retrieverCache.clear();

}

}

至此监听器已经全部注册完毕,都是基于initApplicationEventMulticaster方法生成的广播器进行注册,同时可以看到发布也是基于这个广播器发布的(multicastEvent方法)

这里解释一下通过硬编码添加的监听器的意思 1、新增MyAnnotationConfigApplicationContext类继承AnnotationConfigApplicationContext类重写onRefresh方法添加监听器

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyAnnotationConfigApplicationContext extends AnnotationConfigApplicationContext {

@Override

protected void onRefresh() {

// 硬编码添加监听器

this.addApplicationListener(new TestListener());

}

}

2、 启动类增加springApplication.setApplicationContextClass(MyAnnotationConfigApplicationContext.class);

import com.example.demo.listener.MyAnnotationConfigApplicationContext;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

public class DemoApplication {

public static void main(String[] args) {

SpringApplication springApplication = new SpringApplication(DemoApplication.class);

springApplication.setApplicationContextClass(MyAnnotationConfigApplicationContext.class);

springApplication.run(args);

}

}

3、 这样就可以通过硬编码方式添加监听器了

源码解析-发布(publishEvent)方法

接口ApplicationEventPublisher最终还是调用的实现类AbstractApplicationContext的publishEvent方法

@FunctionalInterface

public interface ApplicationEventPublisher {

default void publishEvent(ApplicationEvent event) {

publishEvent((Object) event);

}

void publishEvent(Object event);

}

@Override

public void publishEvent(ApplicationEvent event) {

publishEvent(event, null);

}

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {

Assert.notNull(event, "Event must not be null");

// 判断事件源是否实现了ApplicationEvent接口并进行转化

ApplicationEvent applicationEvent;

if (event instanceof ApplicationEvent) {

applicationEvent = (ApplicationEvent) event;

}

else {

// 如果没有也要封装成ApplicationEvent事件

applicationEvent = new PayloadApplicationEvent<>(this, event);

if (eventType == null) {

eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();

}

}

// 在初始化应用上下文预处理方法(prepareRefresh)之后,注册监听器方法(registerListeners)之前,这期间的发布全部进行延迟发布,交由registerListeners方法统一发布

// 此时earlyApplicationEvents为null

if (this.earlyApplicationEvents != null) {

this.earlyApplicationEvents.add(applicationEvent);

}

else {

// 获取广播器并发布事件

getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);

}

// 通过父上下文发布事件

if (this.parent != null) {

if (this.parent instanceof AbstractApplicationContext) {

((AbstractApplicationContext) this.parent).publishEvent(event, eventType);

}

else {

this.parent.publishEvent(event);

}

}

}

终于到了广播器的发布方法了

@Override

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {

// 包装事件源,可以方便解析事件源的泛型

ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));

// 获取任务执行(默认为空)

Executor executor = getTaskExecutor();

// 通过事件源和事件类型获取感知的监听器后遍历发布

for (ApplicationListener listener : getApplicationListeners(event, type)) {

// 如果有设置任务执行则使用任务执行发布

if (executor != null) {

executor.execute(() -> invokeListener(listener, event));

}

else {

// 如果没有设置任务执行则直接发布

invokeListener(listener, event);

}

}

}

protected Collection> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {

// 获取事件的源

Object source = event.getSource();

// 事件源的类型

Class sourceType = (source != null ? source.getClass() : null);

// 一个简单类,当做map的key使用,用以区分不同的事件类型并设置缓存

ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

// 尝试从缓存获取

ListenerRetriever retriever = this.retrieverCache.get(cacheKey);

// 如果缓存不为空则返回监听器列表

if (retriever != null) {

return retriever.getApplicationListeners();

}

// 判断类是否可以缓存的

if (this.beanClassLoader == null

|| (ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {

// Fully synchronized building and caching of a ListenerRetriever

synchronized (this.retrievalMutex) {

// 典型的单例,再次尝试获取缓存

retriever = this.retrieverCache.get(cacheKey);

if (retriever != null) {

return retriever.getApplicationListeners();

}

// 创建缓存的数据

retriever = new ListenerRetriever(true);

// 通过事件源查找符合的监听器

Collection> listeners = retrieveApplicationListeners(eventType, sourceType, retriever);

// 设置缓存

this.retrieverCache.put(cacheKey, retriever);

return listeners;

}

}

else {

// 通过事件源查找符合的监听器

return retrieveApplicationListeners(eventType, sourceType, null);

}

}

最终是通过retrieveApplicationListeners方法进行监听器查找的

private Collection> retrieveApplicationListeners(

ResolvableType eventType, @Nullable Class sourceType, @Nullable ListenerRetriever retriever) {

// 查找的监听器集合

List> allListeners = new ArrayList<>();

Set> listeners;

Set listenerBeans;

synchronized (this.retrievalMutex) {

// 获取前面注册监听器方法(registerListeners)注册的监听器

listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);

listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);

}

// 遍历硬编码注册的监听器

for (ApplicationListener listener : listeners) {

// 判断是否符合监听器

if (supportsEvent(listener, eventType, sourceType)) {

if (retriever != null) {

// 为缓存添加的

retriever.applicationListeners.add(listener);

}

// 添加到查找到的监听器中

allListeners.add(listener);

}

}

// 解析通过实现ApplicationListener接口的监听器

if (!listenerBeans.isEmpty()) {

// 获取bean工厂

ConfigurableBeanFactory beanFactory = getBeanFactory();

for (String listenerBeanName : listenerBeans) {

try {

// 判断是否符合监听器

if (supportsEvent(beanFactory, listenerBeanName, eventType)) {

// 通过bean工厂获取监听器

ApplicationListener listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);

// 如果不存在结果集中并且符合需要感知的监听器

if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {

// 如果需要缓存

if (retriever != null) {

// 如果是单例,则添加监听器到缓存,否则添加beanName缓存

if (beanFactory.isSingleton(listenerBeanName)) {

retriever.applicationListeners.add(listener);

}

else {

retriever.applicationListenerBeans.add(listenerBeanName);

}

}

// 添加到查找到的监听器中

allListeners.add(listener);

}

}

else {

// 删除不符合感知的监听器需要移除对应的缓存和监听器结果

Object listener = beanFactory.getSingleton(listenerBeanName);

if (retriever != null) {

retriever.applicationListeners.remove(listener);

}

allListeners.remove(listener);

}

}

catch (NoSuchBeanDefinitionException ex) {

// Singleton listener instance (without backing bean definition) disappeared -

// probably in the middle of the destruction phase

}

}

}

// 对监听器排序,如果存在@Order注解

AnnotationAwareOrderComparator.sort(allListeners);

// 如果applicationListenerBeans为空说明监听器全部在allListeners里,则清空applicationListeners重新添加即可

// applicationListenerBeans为空说明没有非单例bean

if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {

retriever.applicationListeners.clear();

retriever.applicationListeners.addAll(allListeners);

}

// 反正最终查找到的监听器

return allListeners;

}

至此所有匹配的监听器已经找到,至于如何判断是否符合监听器的各位看官有兴趣可以自行了解,最后我们看看发布方法invokeListener

protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {

// 获取异常处理(默认为空,可以手动设置异常处理类)

ErrorHandler errorHandler = getErrorHandler();

if (errorHandler != null) {

try {

// 如果存在异常处理类,则在异常处理类内进行发布通知

doInvokeListener(listener, event);

}

catch (Throwable err) {

errorHandler.handleError(err);

}

}

else {

// 否则直接发布通知

doInvokeListener(listener, event);

}

}

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {

try {

// 调用实现类的onApplicationEvent方法

listener.onApplicationEvent(event);

}

catch (ClassCastException ex) {

String msg = ex.getMessage();

if (msg == null || matchesClassCastMessage(msg, event.getClass())) {

Log logger = LogFactory.getLog(getClass());

if (logger.isTraceEnabled()) {

logger.trace("Non-matching event type for listener: " + listener, ex);

}

}

else {

throw ex;

}

}

}

到这里所有方法解析就结束了

总结

通过阅读源码,我们知道除了基础的应用,spring还为我们提供了哪些功能 1、自己编写一个类实现ApplicationEventMulticaster接口代替默认的SimpleApplicationEventMulticaster广播器 2、通过调用setTaskExecutor(@Nullable Executor taskExecutor)方法制定广播器的执行计划 3、通过调用setErrorHandler(@Nullable ErrorHandler errorHandler)方法异常处理方案 4、在监听器上添加@Order(int)注解制定监听器执行顺序 5、期待留言补充。。。

相关推荐