十一、Spring源码学习之registerListeners方法

registerListeners()方法

protected void registerListeners() {
		// Register statically specified listeners first.
		//获取容器中事件监听并存放到多播器中 applicationListeners
		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);
		//从容器中获取事件监听的beanName 存放到多播器中
		for (String listenerBeanName : 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 (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}

SimpleApplicationEventMulticaster#multicastEvent()方法

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 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())) {
				// Possibly a lambda-defined listener which we could not resolve the generic event type for
				// -> let's suppress the exception and just log a debug message.
				Log logger = LogFactory.getLog(getClass());
				if (logger.isTraceEnabled()) {
					logger.trace("Non-matching event type for listener: " + listener, ex);
				}
			}
			else {
				throw ex;
			}
		}
	}

AbstractApplicationEventMulticaster#getApplicationListeners()方法

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

		Object source = event.getSource();
		Class<?> sourceType = (source != null ? source.getClass() : null);
		//根据事件sourceType和事件Type 构建缓存key
		ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

		// Quick check for existing entry on ConcurrentHashMap...
		//根据key从retrieverCache缓存中获取ListenerRetriever
		//获取监听该事件的所有监听器
		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);
				//根据事件Type和目标sourceType 及缓存 获取符合条件的监听器,并且将监听器放到缓存中
				Collection<ApplicationListener<?>> listeners =
						retrieveApplicationListeners(eventType, sourceType, retriever);
				this.retrieverCache.put(cacheKey, retriever);
				return listeners;
			}
		}
		else {
			// No ListenerRetriever caching -> no synchronization necessary
			return retrieveApplicationListeners(eventType, sourceType, null);
		}
	}

AbstractApplicationEventMulticaster#retrieveApplicationListeners()方法

private Collection<ApplicationListener<?>> retrieveApplicationListeners(
			ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) {

		List<ApplicationListener<?>> allListeners = new ArrayList<>();
		Set<ApplicationListener<?>> listeners;
		Set<String> listenerBeans;
		synchronized (this.retrievalMutex) {
			//将已经存在的所有监听器和beanName 存放到临时集合中
			listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);
			listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);
		}
		//遍历所有的监听器
		for (ApplicationListener<?> listener : listeners) {
			//判断当前监听器是否监听eventType事件
			if (supportsEvent(listener, eventType, sourceType)) {
				if (retriever != null) {
					//是 则放入缓存
					retriever.applicationListeners.add(listener);
				}
				allListeners.add(listener);
			}
		}
		if (!listenerBeans.isEmpty()) {
			BeanFactory beanFactory = getBeanFactory();
			for (String listenerBeanName : listenerBeans) {
				try {
					//遍历所有的监听器beanName
					Class<?> listenerType = beanFactory.getType(listenerBeanName);
					//判断监听器是否监听了该事件
					if (listenerType == null || supportsEvent(listenerType, eventType)) {
						//拿到该监听器
						ApplicationListener<?> listener =
								beanFactory.getBean(listenerBeanName, ApplicationListener.class);
						//如果 allListeners中不存在 && 该监听器确实监听该事件
						if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
							if (retriever != null) {
								//并且该事件是单例bean
								if (beanFactory.isSingleton(listenerBeanName)) {
									//则放入缓存中
									retriever.applicationListeners.add(listener);
								}
								else {
									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
				}
			}
		}
		AnnotationAwareOrderComparator.sort(allListeners);
		//如果缓存对象不是null && applicationListenerBeans是空的
		if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
			retriever.applicationListeners.clear();
			//则将该所有符合条件的监听器放入缓存中
			retriever.applicationListeners.addAll(allListeners);
		}
		return allListeners;
	}

//当前事件是否被当前监听器监听
protected boolean supportsEvent(Class<?> listenerType, ResolvableType eventType) {
		if (GenericApplicationListener.class.isAssignableFrom(listenerType) ||
				SmartApplicationListener.class.isAssignableFrom(listenerType)) {
			return true;
		}
		ResolvableType declaredEventType = GenericApplicationListenerAdapter.resolveDeclaredEventType(listenerType);
		return (declaredEventType == null || declaredEventType.isAssignableFrom(eventType));
	}
protected boolean supportsEvent(
			ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {

		GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
				(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
		return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
	}

相关推荐

  1. Spring学习registerListeners方法

    2024-03-29 11:36:01       31 阅读
  2. Spring学习onRefresh方法

    2024-03-29 11:36:01       35 阅读
  3. 二、Spring学习prepareRefresh方法

    2024-03-29 11:36:01       46 阅读
  4. 九、Spring学习initApplicationEventMulticaster方法

    2024-03-29 11:36:01       41 阅读
  5. Spring推断构造方法解析

    2024-03-29 11:36:01       32 阅读
  6. GDAL剖析(OGR投影说明

    2024-03-29 11:36:01       34 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-29 11:36:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-29 11:36:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-29 11:36:01       82 阅读
  4. Python语言-面向对象

    2024-03-29 11:36:01       91 阅读

热门阅读

  1. FFMPEG对于处理rtp流出现马赛克问题处理

    2024-03-29 11:36:01       43 阅读
  2. Linux curl 类似 postman 直接发送 get/post 请求

    2024-03-29 11:36:01       41 阅读
  3. 大数据导论-大数据分析——沐雨先生

    2024-03-29 11:36:01       38 阅读
  4. 一些常见的zookeeper问题和答案

    2024-03-29 11:36:01       48 阅读
  5. Pytorch:torchvision.transforms.Compose

    2024-03-29 11:36:01       41 阅读
  6. 公网部署ctfd+ctfd_whale问题解决

    2024-03-29 11:36:01       38 阅读
  7. 关于docker-Engine使用的存储驱动devicemapper的常识

    2024-03-29 11:36:01       45 阅读
  8. git2consul+consul+gitlab连接

    2024-03-29 11:36:01       42 阅读
  9. element el-table表格默认勾选toggleRowSelection失效问题

    2024-03-29 11:36:01       41 阅读
  10. Spring Boot 多模块项目跨包自动注入的方法

    2024-03-29 11:36:01       42 阅读
  11. rust - 常用时间处理

    2024-03-29 11:36:01       48 阅读