事件机制-Spring 源码系列(4)
目录:
Ioc容器beanDefinition-Spring 源码(1)
Ioc容器依赖注入-Spring 源码(2)
Ioc容器BeanPostProcessor-Spring 源码(3)
事件机制-Spring 源码(4)
public class EatEvent extends ApplicationEvent { private String status; public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public EatEvent(Object source) { super(source); } }
监听器:
public class MeListener implements ApplicationListener<EatEvent> { public void onApplicationEvent(EatEvent event) { System.out.println("收到通知,可以去吃饭了"); } }
触发事件:
public class TestDo implements ApplicationContextAware { private ApplicationContext applicationContext; public void doTest(){ applicationContext.publishEvent(new EatEvent(this)); } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
以上代码是实际spring项目中经常会用到的,利用spring的事件机制,可以解耦各个具体监听器,在变化的需求中通过增减监听器来减少具体实现的改动。
spring核心是管理bean,而对于这种事件机制,天然有了比较好的实现基础,可以想象这些事件bean在初始化时已经被管理器加入到某个注册表里了,然后事件触发时,就要找容器触发。
网上找的完整的相关类图:
源码实现部分:
首先我们在创建一个Listener的时候,需要把这个bean交给容器管理,由EventMulticaster来管理,从applicationContext.publishEvent(new EatEvent("”))为入口来看源码。
public void publishEvent(ApplicationEvent event) { publishEvent(event, null); } protected void publishEvent(Object event, 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<Object>(this, event); if (eventType == null) { eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass()); } } // 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); } } }
getApplicationEventMulticaster拿预备好的事件广播器,可以使用自己实现的事件广播器,初始化是在AbstractApplicationContext.refresh方法触发initApplicationEventMulticaster():
protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 取applicationEventMulticaster名的bean,如果没有,就用框架的SimpleApplicationEventMulticaster,是个扩展点 if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isDebugEnabled()) { logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isDebugEnabled()) { logger.debug("Unable to locate ApplicationEventMulticaster with name '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "': using default [" + this.applicationEventMulticaster + "]"); } } }
SimpleApplicationEventMulticaster的multicastEvent(applicationEvent, eventType);方法:
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @Override public void run() { invokeListener(listener, event); } }); } else { invokeListener(listener, event); } } }
getApplicationListeners方法来获取对应的监听者:
protected Collection<ApplicationListener<?>> getApplicationListeners( ApplicationEvent event, ResolvableType eventType) { Object source = event.getSource(); Class<?> sourceType = (source != null ? source.getClass() : null); ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType); // Quick check for existing entry on ConcurrentHashMap... 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<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); } }
retrieveApplicationListeners需要从容器中过滤出对应的监听者的bean:
private Collection<ApplicationListener<?>> retrieveApplicationListeners( ResolvableType eventType, Class<?> sourceType, ListenerRetriever retriever) { LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>(); Set<ApplicationListener<?>> listeners; Set<String> listenerBeans; synchronized (this.retrievalMutex) { listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners); listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans); } // 遍历全部监听者,过滤出匹配的 for (ApplicationListener<?> listener : listeners) { 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 { Class<?> listenerType = beanFactory.getType(listenerBeanName); if (listenerType == null || supportsEvent(listenerType, eventType)) { // 就是这行代码从容器中获取 ApplicationListener<?> listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class); if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) { if (retriever != null) { 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); return allListeners; }
Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @Override public void run() { invokeListener(listener, event); } }); }
实现的时候可以通过继承SimpleApplicationEventMulticaster的方式来完成,例子如下:
public class AsyncApplicationEventMulticaster extends SimpleApplicationEventMulticaster { private TaskExecutor taskExecutor = new TaskExecutor() { ExecutorService exeserv = Executors.newCachedThreadPool(); public void execute(Runnable task) { exeserv.execute(task); } }; protected TaskExecutor getTaskExecutor() { return this.taskExecutor; } }
invokeListener来执行onApplicationEvent方法:
protected void invokeListener(ApplicationListener listener, ApplicationEvent event) { ErrorHandler errorHandler = getErrorHandler(); if (errorHandler != null) { try { listener.onApplicationEvent(event); } catch (Throwable err) { errorHandler.handleError(err); } } else { listener.onApplicationEvent(event); } }
到这里,就执行到了onApplicationEvent方法。
另外,回到最前面的例子中,注意EatEvent中那个source属性,代表来源的意思,再调用publish方法时将this传入,那么在筛选监听者的时候,就可以判断是哪个来源的bean发起的通知,再进行一次筛选是否执行的逻辑,如此就是监听者可以过滤事件源了。