文章目录
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
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
添加监听器到applicationListeners和applicationListenerBeans集合
public final Set
@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
@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
// 获取事件的源
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
// 设置缓存
this.retrieverCache.put(cacheKey, retriever);
return listeners;
}
}
else {
// 通过事件源查找符合的监听器
return retrieveApplicationListeners(eventType, sourceType, null);
}
}
最终是通过retrieveApplicationListeners方法进行监听器查找的
private Collection
ResolvableType eventType, @Nullable Class> sourceType, @Nullable ListenerRetriever retriever) {
// 查找的监听器集合
List
Set
Set
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、期待留言补充。。。