目录
获取监听器的入口方法
实际检索监听器的核心方法
监听器类型检查方法
监听器的注册过程
监听器的存储结构
过程总结
Spring源码分析之事件机制——观察者模式(一)-CSDN博客
Spring源码分析之事件机制——观察者模式(二)-CSDN博客
Spring源码分析之事件机制——观察者模式(三)-CSDN博客
这两篇文章是这个篇章的前篇和后篇,感兴趣的读者可以阅读一下,从spring源码分析观察者模式
获取监听器的入口方法
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster {// 存储所有监听器的集合private final DefaultListenerRetrieverdefaultRetriever = new DefaultListenerRetriever();// 缓存事件类型与监听器的映射关系private final Map<ListenerCacheKey, ListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64);protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {// 获取事件源和源类型Object source = event.getSource();Class<?> sourceType = source != null ? source.getClass() : null;// 创建缓存keyListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);// 准备新的缓存检索器CachedListenerRetriever newRetriever = null;// 尝试从缓存中获取已存在的检索器CachedListenerRetriever existingRetriever = (CachedListenerRetriever)this.retrieverCache.get(cacheKey);// 如果缓存中不存在,且类加载器安全(防止类加载器泄漏),则创建新的检索器if (existingRetriever == null && (this.beanClassLoader == null || ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {newRetriever = new CachedListenerRetriever();// 使用CAS操作将新检索器放入缓存existingRetriever = (CachedListenerRetriever)this.retrieverCache.putIfAbsent(cacheKey, newRetriever);if (existingRetriever != null) {newRetriever = null;}}// 如果存在缓存的检索器,尝试获取缓存的监听器if (existingRetriever != null) {Collection<ApplicationListener<?>> result = existingRetriever.getApplicationListeners();if (result != null) {return result;}}// 如果缓存未命中,检索匹配的监听器return retrieveApplicationListeners(eventType, sourceType, newRetriever);
}
这个方法实现了监听器检索的缓存机制,通过缓存来提高性能,同时考虑了类加载器安全性。
实际检索监听器的核心方法
private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable CachedListenerRetriever retriever) {// 存储所有匹配的监听器List<ApplicationListener<?>> allListeners = new ArrayList();// 如果有缓存检索器,创建过滤后的监听器集合Set<ApplicationListener<?>> filteredListeners = retriever != null ? new LinkedHashSet() : null;Set<String> filteredListenerBeans = retriever != null ? new LinkedHashSet() : null;// 同步获取已注册的监听器和监听器Bean名称Set<ApplicationListener<?>> listeners;Set<String> listenerBeans;synchronized(this.defaultRetriever) {listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);}// 处理已实例化的监听器for(ApplicationListener<?> listener : listeners) {if (supportsEvent(listener, eventType, sourceType)) {if (retriever != null) {filteredListeners.add(listener);}allListeners.add(listener);}}// 处理监听器Beanif (!listenerBeans.isEmpty()) {ConfigurableBeanFactory beanFactory = getBeanFactory();for(String listenerBeanName : listenerBeans) {try {// 检查Bean是否支持该事件if (supportsEvent(beanFactory, listenerBeanName, eventType)) {ApplicationListener<?> listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);// 避免重复添加if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {// 根据Bean的作用域决定是否缓存if (retriever != null) {if (beanFactory.isSingleton(listenerBeanName)) {filteredListeners.add(listener);} else {filteredListenerBeans.add(listenerBeanName);}}allListeners.add(listener);}} else {// 移除不支持的监听器Object listener = beanFactory.getSingleton(listenerBeanName);if (retriever != null) {filteredListeners.remove(listener);}allListeners.remove(listener);}} catch (NoSuchBeanDefinitionException ex) {// 忽略不存在的Bean}}}// 按照@Order注解排序AnnotationAwareOrderComparator.sort(allListeners);// 更新缓存if (retriever != null) {if (filteredListenerBeans.isEmpty()) {retriever.applicationListeners = new LinkedHashSet(allListeners);retriever.applicationListenerBeans = filteredListenerBeans;} else {retriever.applicationListeners = filteredListeners;retriever.applicationListenerBeans = filteredListenerBeans;}}return allListeners;
}
这个方法是实际检索监听器的核心实现,它处理了已实例化的监听器和尚未实例化的监听器Bean,同时考虑了Bean的作用域和缓存策略。
监听器类型检查方法
private boolean supportsEvent(ConfigurableBeanFactory beanFactory, String listenerBeanName, ResolvableType eventType) {// 获取监听器的类型Class<?> listenerType = beanFactory.getType(listenerBeanName);// 如果是特殊的监听器类型,直接返回trueif (listenerType != null && !GenericApplicationListener.class.isAssignableFrom(listenerType) && !SmartApplicationListener.class.isAssignableFrom(listenerType)) {// 检查是否支持事件类型if (!supportsEvent(listenerType, eventType)) {return false;}try {// 获取Bean定义并检查泛型类型BeanDefinition bd = beanFactory.getMergedBeanDefinition(listenerBeanName);ResolvableType genericEventType = bd.getResolvableType().as(ApplicationListener.class).getGeneric(new int[0]);return genericEventType == ResolvableType.NONE || genericEventType.isAssignableFrom(eventType);} catch (NoSuchBeanDefinitionException ex) {return true;}}return true;
}
这个方法负责检查监听器是否支持特定的事件类型,它考虑了泛型类型和特殊的监听器接口。整个实现展示了Spring如何高效地管理和匹配事件监听器,通过缓存机制提高性能,同时保证类型安全和正确的监听器顺序。这种实现既保证了功能的完整性,又确保了运行时的效率。
监听器的注册过程
public abstract class AbstractApplicationContext {// 在容器刷新过程中注册监听器protected void registerListeners() {// 首先注册静态指定的监听器for (ApplicationListener<?> listener : getApplicationListeners()) {getApplicationEventMulticaster().addApplicationListener(listener);}// 获取配置的监听器Bean名称String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);for (String listenerBeanName : listenerBeanNames) {// 将监听器Bean名称添加到多播器getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);}// 发布早期事件Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;this.earlyApplicationEvents = null;if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {for (ApplicationEvent earlyEvent : earlyEventsToProcess) {getApplicationEventMulticaster().multicastEvent(earlyEvent);}}}
}
这段代码展示了Spring如何在容器启动时注册监听器。对于像UserCacheListener这样的组件,它们会被Spring容器扫描并注册到ApplicationEventMulticaster中。
监听器的存储结构
private class CachedListenerRetriever {@Nullablepublic volatile Set<ApplicationListener<?>> applicationListeners;@Nullablepublic volatile Set<String> applicationListenerBeans;private CachedListenerRetriever() {}@Nullablepublic Collection<ApplicationListener<?>> getApplicationListeners() {Set<ApplicationListener<?>> applicationListeners = this.applicationListeners;Set<String> applicationListenerBeans = this.applicationListenerBeans;if (applicationListeners != null && applicationListenerBeans != null) {List<ApplicationListener<?>> allListeners = new ArrayList(applicationListeners.size() + applicationListenerBeans.size());allListeners.addAll(applicationListeners);if (!applicationListenerBeans.isEmpty()) {BeanFactory beanFactory = AbstractApplicationEventMulticaster.this.getBeanFactory();for(String listenerBeanName : applicationListenerBeans) {try {allListeners.add(beanFactory.getBean(listenerBeanName, ApplicationListener.class));} catch (NoSuchBeanDefinitionException var8) {}}}if (!applicationListenerBeans.isEmpty()) {AnnotationAwareOrderComparator.sort(allListeners);}return allListeners;} else {return null;}}}
CachedListenerRetriever 其实是AbstractApplicationEventMulticaster 的静态内部类
过程总结
Spring扫描到@Component注解,创建BeanDefinition
Spring容器启动时实例化Bean
在AbstractApplicationContext.registerListeners()中注册