Spring中的设计模式--观察者模式
spring在容器中使用了观察者模式:
一、spring事件:ApplicationEvent,该抽象类继承了EventObject类,jdk建议所有的事件都应该继承自EventObject。
二、spring事件监听器:ApplicationLisener,该接口继承了EventListener接口,jdk建议所有的事件监听器都应该继承EventListener。
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /** * Handle an application event. * @param event the event to respond to */ void onApplicationEvent(E event); }
三、spring事件发布:ApplicationEventPublisher 。 ApplicationContext继承了该接口,在ApplicationContext的抽象类AbstractApplicationContext中做了实现。
package org.springframework.context; public interface ApplicationEventPublisher {
/**
* Notify all <strong>matching</strong> listeners registered with this
* application of an application event. Events may be framework events
* (such as RequestHandledEvent) or application-specific events.
* @param event the event to publish
* @see org.springframework.web.context.support.RequestHandledEvent
*/
void publishEvent(ApplicationEvent var1); void publishEvent(Object var1); }
AbstractApplicationContext类中publishEvent方法实现:
/** * Publish the given event to all listeners. * <p>Note: Listeners get initialized after the MessageSource, to be able * to access it within listener implementations. Thus, MessageSource * implementations cannot publish events. * @param event the event to publish (may be an {@link ApplicationEvent} * or a payload object to be turned into a {@link PayloadApplicationEvent}) */ @Override public void publishEvent(Object event) { publishEvent(event, null); } /** * Publish the given event to all listeners. * @param event the event to publish (may be an {@link ApplicationEvent} * or a payload object to be turned into a {@link PayloadApplicationEvent}) * @param eventType the resolved event type, if known * @since 4.2 */ protected void publishEvent(Object event, @Nullable ResolvableType eventType) { Assert.notNull(event, "Event must not be null"); if (logger.isTraceEnabled()) { logger.trace("Publishing event in " + getDisplayName() + ": " + event); } // Decorate event as an ApplicationEvent if necessary ApplicationEvent applicationEvent; if (event instanceof ApplicationEvent) { applicationEvent = (ApplicationEvent) event; } else { applicationEvent = new PayloadApplicationEvent<>(this, event); if (eventType == null) { eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType(); } } // Multicast right now if possible - or lazily once the multicaster is initialized if (this.earlyApplicationEvents != null) { this.earlyApplicationEvents.add(applicationEvent); } else {
//事件广播委托给ApplicationEventMulticaster来进行 getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); } // Publish event via parent context as well... if (this.parent != null) { if (this.parent instanceof AbstractApplicationContext) { ((AbstractApplicationContext) this.parent).publishEvent(event, eventType); } else { this.parent.publishEvent(event); } } }
由上代码可知,AbstractApplicationContext类并没有具体的做事件广播,而是委托给ApplicationEventMulticaster来进行,ApplicationEventMulticaster的multicastEvent()方法实现如下:
@Override public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); 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 = this.getErrorHandler(); if (errorHandler != null) { try { listener.onApplicationEvent(event); } catch (Throwable var6) { errorHandler.handleError(var6); } } else { try { listener.onApplicationEvent(event); } catch (ClassCastException var5) { LogFactory.getLog(this.getClass()).debug("Non-matching event type for listener: " + listener, var5); } } }
获得listener集合,遍历listener触发事件Executor接口有多个实现类,可以支持同步或异步广播事件。
问题:spring容器是怎么根据事件去找到事件对应的事件监听器呢?
一、入口
private ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:/spring/applicationContext.xml");
二、生成Spring上下文ApplicationContext
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); this.setConfigLocations(configLocations); if (refresh) { this.refresh(); } }
三、调用spring容器初始化方法
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. postProcessBeanFactory(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(); // 初始化事件监听器 // Check for listener beans and register them. 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(); } } }
3.1 initApplicationEventMulticaster()方法代码
protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = this.getBeanFactory(); //先查找BeanFactory配置文件中是否有ApplicationEventMulticaster if (beanFactory.containsLocalBean("applicationEventMulticaster")) { this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class); if (this.logger.isDebugEnabled()) { this.logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else {// 如果beanFactory中没有,则创建一个SimpleApplicationEventMulticaster this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster); if (this.logger.isDebugEnabled()) { this.logger.debug("Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [" + this.applicationEventMulticaster + "]"); } } }
spring先从beanFactory中获取ApplicationEventMulticaster,如果没有自定义,则创建一个SimpleApplicationEventMulticaster。
ApplicationEventMulticaster包含以下属性:defaultRetriever即为注册表,注册监听事件的相关消息; retrieverCache用来做defaultRetriever的缓存。
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware { private final AbstractApplicationEventMulticaster.ListenerRetriever defaultRetriever = new AbstractApplicationEventMulticaster.ListenerRetriever(false); final Map<AbstractApplicationEventMulticaster.ListenerCacheKey, AbstractApplicationEventMulticaster.ListenerRetriever> retrieverCache = new ConcurrentHashMap(64); private ClassLoader beanClassLoader; private BeanFactory beanFactory; private Object retrievalMutex; }
ListenerRetriever的数据结构如下:applicationListeners用来存放监听事件, applicationListenerBeans为存放监听事件的类名称。
private class ListenerRetriever { public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet(); public final Set<String> applicationListenerBeans = new LinkedHashSet(); private final boolean preFiltered;
ListenerCacheKey的数据结构如下:eventType是事件类型,sourceType是事件的源类型,即为事件的构造函数的参数类型。
private static class ListenerCacheKey { private final ResolvableType eventType; private final Class<?> sourceType;
3.2 registerListeners()方法代码
初始化注册表以后,则把事件注册到注册表中,registerListeners()
protected void registerListeners() { //获取所有的listener的迭代器 Iterator var1 = this.getApplicationListeners().iterator(); while(var1.hasNext()) { ApplicationListener<?> listener = (ApplicationListener)var1.next(); //把获取所有的listener, 把事件的bean放到ApplicationEventMulticaster中的ApplicationListener this.getApplicationEventMulticaster().addApplicationListener(listener); } String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false); String[] var7 = listenerBeanNames; int var3 = listenerBeanNames.length; for(int var4 = 0; var4 < var3; ++var4) { String listenerBeanName = var7[var4]; //把事件的名称放到ApplicationListenerBean里去
this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { Iterator var9 = earlyEventsToProcess.iterator(); while(var9.hasNext()) { ApplicationEvent earlyEvent = (ApplicationEvent)var9.next(); this.getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }
3.3 finishBeanFactoryInitialization(beanFactory)
具体会执行到下面的方法,会把AbstractApplicationEventMulticaster的defaultRetriever属性赋值。
执行PostProcessorRegistrationDelegate类的postProcessAfterInitialization()方法:
public Object postProcessAfterInitialization(Object bean, String beanName) { if (this.applicationContext != null && bean instanceof ApplicationListener) { Boolean flag = (Boolean)this.singletonNames.get(beanName); if (Boolean.TRUE.equals(flag)) { this.applicationContext.addApplicationListener((ApplicationListener)bean); } else if (flag == null) { if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) { logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " + "but is not reachable for event multicasting by its containing ApplicationContext " + "because it does not have singleton scope. Only top-level listener beans are allowed " + "to be of non-singleton scope."); } this.singletonNames.put(beanName, Boolean.FALSE); } } return bean; }
执行AbstractApplicationContext类的addApplicationListener()方法:
public void addApplicationListener(ApplicationListener<?> listener) { if (this.applicationEventMulticaster != null) { this.applicationEventMulticaster.addApplicationListener(listener); } else { this.applicationListeners.add(listener); } }
执行AbstractApplicationEventMulticaster类的addApplicationListener()方法
public void addApplicationListener(ApplicationListener<?> listener) { Object var2 = this.retrievalMutex; synchronized(this.retrievalMutex) { this.defaultRetriever.applicationListeners.add(listener); this.retrieverCache.clear(); } }
【spring根据反射机制,通过方法getBeansOfType()获取所有继承了ApplicationListener接口的监听器,然后把监听器全放到注册表里,所以我们可以在spring配置文件中配置自定义的监听器,在spring初始化的时候会把监听器自动注册到注册表中。】
3.4 finishRefresh()
里面执行发布事件。
protected void finishRefresh() { this.initLifecycleProcessor(); this.getLifecycleProcessor().onRefresh(); this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this))); LiveBeansView.registerApplicationContext(this); }
在applicationContext发布事件的时候。
public void publishEvent(ApplicationEvent event) { this.publishEvent(event, (ResolvableType)null); } public void publishEvent(Object event) { this.publishEvent(event, (ResolvableType)null); } protected void publishEvent(Object event, ResolvableType eventType) { Assert.notNull(event, "Event must not be null"); if (this.logger.isTraceEnabled()) { this.logger.trace("Publishing event in " + this.getDisplayName() + ": " + event); } Object applicationEvent; if (event instanceof ApplicationEvent) { applicationEvent = (ApplicationEvent)event; } else { applicationEvent = new PayloadApplicationEvent(this, event); if (eventType == null) { eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType(); } } if (this.earlyApplicationEvents != null) { this.earlyApplicationEvents.add(applicationEvent); } else { // 调用ApplicationEventMulticaster的multicastEvent()方法
this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType); } if (this.parent != null) { if (this.parent instanceof AbstractApplicationContext) { ((AbstractApplicationContext)this.parent).publishEvent(event, eventType); } else { this.parent.publishEvent(event); } } }
AbstractApplicationContext类并没有具体的做事件广播,而是委托给ApplicationEventMulticaster来进行。
ApplicationEventMulticaster的方法multicastEvent()为:public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event); Iterator var4 = this.getApplicationListeners(event, type).iterator(); while(var4.hasNext()) { final ApplicationListener<?> listener = (ApplicationListener)var4.next(); Executor executor = this.getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { public void run() { SimpleApplicationEventMulticaster.this.invokeListener(listener, event); } }); } else { this.invokeListener(listener, event); } } }
根据事件和类型获取所有的监听器方法: getApplicationListeners()
protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) { Object source = event.getSource(); Class<?> sourceType = source != null ? source.getClass() : null; AbstractApplicationEventMulticaster.ListenerCacheKey cacheKey = new AbstractApplicationEventMulticaster.ListenerCacheKey(eventType, sourceType); AbstractApplicationEventMulticaster.ListenerRetriever retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey);
//从缓存里查找ListenerRetriever if (retriever != null) { return retriever.getApplicationListeners(); } else if (this.beanClassLoader == null || ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) && (sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader))) { Object var7 = this.retrievalMutex; synchronized(this.retrievalMutex) { retriever = (AbstractApplicationEventMulticaster.ListenerRetriever)this.retrieverCache.get(cacheKey); if (retriever != null) { return retriever.getApplicationListeners(); } else {
//如果缓存里不存在,则去获得 retriever = new AbstractApplicationEventMulticaster.ListenerRetriever(true); Collection<ApplicationListener<?>> listeners = this.retrieveApplicationListeners(eventType, sourceType, retriever); this.retrieverCache.put(cacheKey, retriever); return listeners; } } } else { return this.retrieveApplicationListeners(eventType, sourceType, (AbstractApplicationEventMulticaster.ListenerRetriever)null); } }
private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, Class<?> sourceType, AbstractApplicationEventMulticaster.ListenerRetriever retriever) { LinkedList<ApplicationListener<?>> allListeners = new LinkedList(); Object var7 = this.retrievalMutex; LinkedHashSet listeners; LinkedHashSet listenerBeans; synchronized(this.retrievalMutex) {
//获取注册表里所有的listener, defaultRetriever在前面已被赋值 listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners); listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans); } Iterator var14 = listeners.iterator(); while(var14.hasNext()) { ApplicationListener<?> listener = (ApplicationListener)var14.next();
//根据事件类型,事件源类型,获取所需要的监听事件 if (this.supportsEvent(listener, eventType, sourceType)) { if (retriever != null) { retriever.applicationListeners.add(listener); } allListeners.add(listener); } } if (!listenerBeans.isEmpty()) { BeanFactory beanFactory = this.getBeanFactory(); Iterator var16 = listenerBeans.iterator(); while(var16.hasNext()) { String listenerBeanName = (String)var16.next(); try { Class<?> listenerType = beanFactory.getType(listenerBeanName); if (listenerType == null || this.supportsEvent(listenerType, eventType)) { ApplicationListener<?> listener = (ApplicationListener)beanFactory.getBean(listenerBeanName, ApplicationListener.class); if (!allListeners.contains(listener) && this.supportsEvent(listener, eventType, sourceType)) { if (retriever != null) { retriever.applicationListenerBeans.add(listenerBeanName); } allListeners.add(listener); } } } catch (NoSuchBeanDefinitionException var13) { ; } } } AnnotationAwareOrderComparator.sort(allListeners); return allListeners; }
配合上面的注解,即可理解,根据事件和事件类型找到对应的监听器,那么如何根据事件类型找到对应的监听器呢?
上面方法中的supportsEvent(listener, eventType, sourceType)方法实现了根据事件类型查找对应的监听器,代码具体实现为:
protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, Class<?> sourceType) { GenericApplicationListener smartListener = listener instanceof GenericApplicationListener ? (GenericApplicationListener)listener : new GenericApplicationListenerAdapter(listener); return ((GenericApplicationListener)smartListener).supportsEventType(eventType) && ((GenericApplicationListener)smartListener).supportsSourceType(sourceType); }
如上可知:上面方法的返回结果跟方法smartListener.supportsEventType(eventType)和smartListener.supportsSourceType(sourceType)有关。
smartListener.supportsEventType(eventType)方法实现为:
public boolean supportsEventType(ResolvableType eventType) { if (this.delegate instanceof SmartApplicationListener) { Class<? extends ApplicationEvent> eventClass = eventType.getRawClass(); return ((SmartApplicationListener)this.delegate).supportsEventType(eventClass); } else { return this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType); } }
该方法主要的逻辑就是根据事件类型判断是否和监听器参数泛型的类型是否一致。
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /** * Handle an application event. * @param event the event to respond to */ void onApplicationEvent(E event); }
在定义自己的监听器要明确指定参数泛型,表明该监听器支持的事件,如果不指明具体的泛型,则没有监听器监听事件。
smartListener.supportsSourceType(sourceType)方法的实现为:
public boolean supportsSourceType(Class<?> sourceType) { return this.delegate instanceof SmartApplicationListener ? ((SmartApplicationListener)this.delegate).supportsSourceType(sourceType) : true; }
以上是spring的事件体系。
四、自定义事件和监听器
我们可以使用spring的事件广播体系,自定义自己的事件:
自定义事件,继承ApplicationEvent:
public class DIYEvent extends ApplicationEvent { private static final long serialVersionUID = 7099057708183571977L; public DIYEvent(String source) { super(source); } }
自定义listener,继承ApplicationListener
@Component public class DIYListener implements ApplicationListener<DIYEvent> { @Override public void onApplicationEvent(DIYEvent diyEvent) { System.out.println("自定义监听器执行"); System.out.println(diyEvent.getSource()); } }
测试触发事件:
public class DIYTest{ private ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:/spring/applicationContext.xml"); @Test public void diyTest(){ applicationContext.publishEvent(new DIYEvent("测试数据")); } }
获取ApplicationContext,发布事件。
调试结果:
自定义监听器执行
测试数据