开发者

Spring ApplicationListener源码解析

目录
  • 正文
  • ApplicationListener介绍
  • ApplicationListener使用
    • 定义事件:
    • 定义事件的监听者
    • 发布事件
    • 监听者收到发布的事件信息
  • ApplicationListener作用
    • ApplicationListener注册
      • ApplicationListener执行
        • 总结

          正文

          对于ApplicationListener使用Spring的应该也熟悉,因为这就是我们平时学习的观察者模式的实际代表。

          Spring基于Java提供的EventListener实现了一套以Spring容器为基础的观察者模式的事件监听功能,

          用于只要实现Spring提供的接口完成事件的定义和监听者的定义,那么就可以很快速的接入观察者模式的实现。

          ApplicationListener介绍

          说ApplicationListener之前先要知道EventListener。

          EventListener本身是一个接口,它的作用跟前面讲到的Aware类似,都是只定义最顶级的接口,并没有实习对应的方法,并且该接口也是由JDK提供的,并不是直接由Spring提供,Spring只是基于该接口实现了自己的一套事件监听功能。

          在Spring中实现事件监听的接口是ApplicationListener,该接口继承了EventListener,并做了对应的实现。

          源码如下:

          package java.util;
          /**
           * A tagging interface that all event listener interfaces must extend.
           * @since JDK1.1
           */
          public interface EventListener {
          }
          
          @FunctionalInterface
          public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
          	//监听者监听事件的逻辑处理
          	void onApplicationEvent(E event);
          	static <T> ApplicationListener<PayloadApplicationEvent<T>> forPayload(Consumer<T> consumer) {
          		return event -> consumer.accept(event.getPayload());
          	}
          }
          

          ApplicationListener使用

          对于ApplicationListener的使用,因为Spring已经做了自己的封装,并且以Spring容器为基础做了实现,那么开发者使用时也可以很快的上手,只要简单的配置即可。

          定义事件:

          //事件继承Spring中的ApplicationEvent
          public class MyEvent extends ApplicationEvent {
              private String name;
              public MyEvent(ApplicationContext source,String name) {
                  super(source);
                  this.name = name;
              }
              public String getName() {
                  return name;
              }
          }
          

          定义事件的监听者

          //定义监听者实现ApplicationListener,并通过泛型声明监听的事件
          @Component
          public class MyEventListener implements ApplicationListener<MyEvent> {
              @Override
              public void onApplicationEvent(MyEvent event) {
                  System.out.println("监听MyEvent:收到消息时间:"+event.getTimestamp()+"【消息name:"+event.getName() + "】");
              }
          }
          
          @Component
          public class MyEventProcessor implements ApplicationContextAware {
              private ApplicationContext applicationContext;
              @Override
              public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
                  this.applicationContext = applicationContext;
              }
              public ApplicationContext getApplicationContext() {
                  return applicationContext;
              }
          }
          

          发布事件

          @SpringBootApplication
          public class BootApplication {
              @Resource
              private DefaultListableBeanFactory defaultListableBeanFactory;
              @Resource
              private MySpringAware mySpringAware;
              @Resource
              private MyEventProcessor myEventProcessor;
           python   public static void main(String[] args) {
                  SpringApplication.run(BootApplication.class,args);
              }
              @PostConstruct
              public void init() {
                  ApplicationContext applicationContext = myEventProcessor.getApplicationContext();
                  //发布事件,事件发布之后,前面订阅的监听者就会监听到该事件发布的消息
                  applicationContext.publishEvent(new MyEvent(applicationContext,"陈汤姆"));
                  applicationContext.publishEvent(new MyEvent(applicationContext,"陈汤姆2"));
              编程客栈}
          }
          

          监听者收到发布的事件信息

          Spring ApplicationListener源码解析

          ApplicationListener作用

          从以上的例子中可以看到ApplicationListner的模式就是设计模式中的观察者模式。

          观察者模式的作用很好的解决了同步交互的问题。

          以发送者和接收者为例,接收者接收消息如果同步场景下需要与发送者实现同步调用,但是这样就导致两者之间无法解耦,而ApplicationListener就是解决同步的问题,ApplicationListener可以提供半解耦的方式实现两者之间的交互,即发送者发送消息不需要与接收者之间实现同步通知,只要订阅发送者的事件即可完成双发的交互。

          这里为什么是半解耦,因为两者之间还是有一定交互的,交互的点就在于发送者的发送方需要维护一个接收者的集合,发送方在发送时需要将具体的接收者放在集合中,在发送时通过遍历集合发送给接收方,执行接收方的业务处理。

          在ApplicationListener这个集合就是public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>(); 这个集合中就存储了接收者的实例,最终会遍历该集合执行接收者的业务逻辑。

          这里抛一个问题,其实ApplicationListener的功能通过MQ也可以实现,那么观察者模式发布订阅模式的区别是什么呢?欢迎评论区一起讨论!

          ApplicationListener注册

          对于ApplicationListener的注册比较好梳理的,只要找到存储ApplicationListener的集合就可以知道怎么add集合的。

          在Spring中ApplicationListener的注册也是在Spring中实现的。

          具体的梳理逻辑如下:

          org.springframework.context.support.AbstractApplicationContext#refresh

          org.springframework.context.support.AbstractApplicationContext#registerListeners

          org.springframework.context.event.AbstractApplicationEventMulticaster#addApplicationListener

          源码梳理如下:

          public abstract class AbstractApplicationContext extends DefaultResourceLoader
          		implements ConfigurableApplicationContext {
              @Override
          	public void refresh() throws BeansException, IllegalStateException {
          		synchronized (this.startupShutdownMonitor) {
          			// Prepare this context for refreshing.
          			prepareRefresh();
          			// Tell the subclass to refresh the internal bean factory.
          			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
          			// Prepare the bean factory for use in this context.
          			prepareBeanFactory(beanFactory);
          			try {
          				// Allows post-processing of the bean factory in context subclasses.
          				androidpostProcessBeanFactory(beanFactory);
          				// Invoke factory processors registered as beans in the context.
          				invokeBeanFactoryPostProcessors(beanFactory);
          				// Register bean processors that intercept bean creation.
          				registerBeanPostProcessors(beanFactory);
          				// Initialize message source for this context.
          				initMessageSource();
          				// Initialize event multicaster for this context.
          				initApplicationEventMulticaster();
          				// Initialize other special beans in specific context subclasses.
          				onRefresh();
          				//注册观察者
          				registerListeners();
          				// Instantiate all remaining (non-lazy-init) singletons.
          				finishBeanFactoryInitialization(beanFactory);
          				// Last step: publish corresponding event.
          				finishRefresh();
          			}
          			catch (BeansException ex) {
          				if (logger.isWarnEnabled()) {
          					logger.warn("Exception encountered during context initialization - " +
          							"cancelling refresh attempt: " + ex);
          				}
          				// Destroy already created singletons to avoid dangling resources.
          				destroyBeans();
          				// Reset 'active' flag.
          				cancelRefresh(ex);
          				// Propagate exception to caller.
          				throw ex;
          			}
          			finally {
          				// Reset common introspection caches in Spring's core, since we
          				// might not ever need metadata for singleton beans anymore...
          				resetCommonCaches();
          			}
          		}
          	}
              //将观察者注入到集合中
          	protected void registerListeners() {
          		// 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[] listenerBeaiwXsKRXnNames = getBeanNamesForType(ApplicationListener.class, true, false);
          		for (String listenerBeanName : listenerBeanNames) {
                      //调用集合的add操作
          			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
          		}
          		// Publish early application events now that we finally have a multicaster...
          		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
          		this.earlyApplicationEvents = null;
          		if (earlyEventsToProcess != null) {
          			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                          //获取观察者的集合
          				getApplicationEventMulticaster().multicastEvent(earlyEvent);
          			}
          		}
          	}
          }
          
          public abstract class AbstractApplicationEventMulticaster
          		implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
          	private class ListenerRetriever {
                  //存储观察者的集合
          		public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
          		public final Set<String> applicationListenerBeans = new LinkedHashSet<>();
          		private final boolean preFiltered;
          		public ListenerRetriever(boolean preFiltered) {
          			this.preFiltered = preFiltered;
          		}
                  //获取观察者的集合
          		public Collection<ApplicationListener<?>> getApplicationListeners() {
          			List<ApplicationListener<?>> allListeners = new ArrayList<>(
          					this.applicationListeners.size() + this.applicationListenerBeans.size());
          			allListeners.addAll(this.applicationListeners);
          			if (!this.applicationListenerBeans.isEmpty()) {
          				BeanFactory beanFactory = getBeanFactory();
          				for (String listenerBeanName : this.applicationListenerBeans) {
          					try {
          						ApplicationListener<?> listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
          						if (this.preFiltered || !allListeners.contains(listener)) {
          							allListeners.add(listener);
          						}
          					}
          					catch (NoSuchBeanDefinitionException ex) {
          						// Singleton listener instance (without backing bean definition) disappeared -
          						// probably in the middle of the destruction phase
          					}
          				}
          			}
          			if (!this.preFiltered || !this.applicationListenerBeans.isEmpty()) {
          				AnnotationAwareOrderComparator.sort(allListeners);
          			}
          			return allListeners;
          		}
          	}
          }
          

          从以上的源码可以看到核心的集合就是applicationListeners。可以根据该集合梳理注册和执行流程。

          ApplicationListener执行

          注册梳理清晰,那么执行自然也很好梳理了, 毕竟使用的都是同一个集合。

          ApplicationListener的执行其实就是观察者的执行,也就是在使用篇章中的MyEventListener,在MyEventListener中重写了onApplicationEvent,其中实现了自己的逻辑,那么执行就是将MyEventListener中重写的方式如何在没有同步调用的情况下执行。

          执行的实现就是依赖观察者的集合,在注册中我们已经将所有的观察者添加到了ApplicationListener集合中,只要将该集合中的观察者取出执行,即可完成半解耦的执行。

          梳理流程如下:

          org.springframework.context.ApplicationEventPublisher#publishEvent(org.springframework.context.ApplicationEvent)

          org.springframework.context.support.AbstractApplicationContext#publishEvent(java.lang.Object, org.springframework.core.ResolvableType)

          org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)

          org.springframework.context.event.SimpleApplicationEventMulticaster#invokeListener

          org.springframework.context.event.SimpleApplicationEventMulticaster#doInvokeListener

          源码如下:

          public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
          	@Override
          	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
          		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
                  //getApplicationListeners就是获取ApplicationListener的集合
          		for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
          			Executor executor = getTaskExecutor();
          			if (executor != null) {
                          //执行监听者的
          				executor.execute(() -> invokeListener(listener, event));
          			}
          			else {
          				invokeListener(listener, event);
          			}
          		}
          	}
              //执行监听者逻辑
              protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
          		ErrorHandler errorHandler = g开发者_Go开发etErrorHandler();
          		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.isDebugEnabled()) {
          					logger.debug("Non-matching event type for listener: " + listener, ex);
          				}
          			}
          			else {
          				throw ex;
          			}
          		}
          	}
          }
          

          总结

          从以上的梳理中,对ApplicationListener的逻辑做一个总结,对于ApplicationListener整体逻辑梳理如下:

          • 定义事件:MyEvent就是自定义的事件
          • 定义监听者:MyEventListener就是自定义的MyEvent的事件监听者,只要MyEvent事件被触发,那么MyEventListener就会自动执行
          • 监听者注册:将MyEventListener注册到ApplicationListener集合中
          • 发布事js件:将自定的MyEvent发布,发布之后监听者就会收到通知
          • 读取注册的监听者:将前面注册到ApplicationListner集合的数据读取
          • 执行监听者监听逻辑:将读取到的ApplicationListner集合执行MyEventListner的onApplicationEvent

          以上就是自己关于Spring中ApplicationListener的理解,更多关于Spring ApplicationListener的资料请关注我们其它相关文章!

          0

          上一篇:

          下一篇:

          精彩评论

          暂无评论...
          验证码 换一张
          取 消

          最新开发

          开发排行榜