1 背景 在业务开发中,经常是多人协同开发。常有”业务A完成后,需要通知业务B”的场景,最平常的写法就是直接在业务A后面增加业务B的调用。这样的缺点就是业务逻辑耦合,一旦业务C也需要业务A的结果时,就不得不在业务A后面新增调用业务C的代码。
针对这种监听事件,第一时间想到的就是”观察者模式”。使用该模式,新增业务C监听的时候,不需要改动业务A的代码。做到了业务代码的解耦。
Spring重写了Java自带的事件监听。
org.springframework.context.ApplicationEvent
继承 java.util.EventObject
org.springframework.context.ApplicationListener
继承 java.util.EventListener
2 使用 springframework 中有许多内建的 ApplicationEvent
,这里就不做过多的描述,主要针对自定义事件的使用。
2.1 自定义事件监听 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public static void main (String[] args) { GenericApplicationContext context = new GenericApplicationContext(); context.registerBean(MyApplicationListener.class); context.refresh(); context.publishEvent(new MyApplicationEvent("Hello World" )); context.close(); context.publishEvent(new MyApplicationEvent("Hello World Again" )); } public static class MyApplicationEvent extends ApplicationEvent { public MyApplicationEvent (String source) { super (source); } } public static class MyApplicationListener implements ApplicationListener <MyApplicationEvent > { @Override public void onApplicationEvent (MyApplicationEvent event) { System.out.println(event.getClass().getSimpleName()); } }
上述是测试Demo,注意:ApplicationListener
必须是 Spring 管理的 Bean,并且监听方法必须是 public
。
正式项目中,可以按照如下格式使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Component public class MyApplicationListener implements ApplicationListener <MyApplicationEvent > { @Override public void onApplicationEvent (MyApplicationEvent event) { System.out.println(event.getClass().getSimpleName()); } } public class MyApplicationEvent extends ApplicationEvent { public MyApplicationEvent (String source) { super (source); } } @Service public class MyApplicationEventService { @Autowired private ApplicationEventPublisher applicationEventPublisher; public void publishEvent () { applicationEventPublisher.publishEvent(new MyApplicationEvent("Hello MyApplicationEvent" )); } }
2.2 注解实现自定义事件监听 自Spring4.2引入了 org.springframework.context.event.EventListener
注解。使用注解的话,上面中的 MyApplicationListener
, 就可以按照如下改写。
1 2 3 4 5 6 7 @Component public class MyApplicationListener { @EventListener(MyApplicationEvent.class) public void onApplicationEvent (MyApplicationEvent event) { System.out.println(event.getClass().getSimpleName()); } }
并且,@EventListener
还支持继承,可以在抽象类上使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public abstract class AbstractEventListener { @EventListener(ContextRefreshedEvent.class) public void onContextRefreshedEvent (ContextRefreshedEvent event) { System.out.println("AbstractEventListener : " + event.getClass().getSimpleName()); } } public class MyEventListener extends AbstractEventListener { @EventListener(ContextClosedEvent.class) public boolean onContextClosedEvent (ContextClosedEvent event) { System.out.println("MyEventListener : " + event.getClass().getSimpleName()); return true ; } }
同时,@EventListener
还支持多事件监听。
1 2 3 4 5 6 7 8 9 10 11 12 13 public static class MyMultiEventsListener { @EventListener({ContextRefreshedEvent.class, ContextClosedEvent.class}) public void onEvent () { System.out.println("onEvent" ); } @EventListener({ContextRefreshedEvent.class, ContextClosedEvent.class}) public void onApplicationContextEvent (ApplicationContextEvent event) { System.out.println("onApplicationContextEvent : " + event.getClass().getSimpleName()); } }
ApplicationContextEvent
同时是以上两个类的父类。
2.3 泛型事件监听 Spring还提供了针对泛型事件监听。泛型事件,必须实现org.springframework.core.ResolvableTypeProvider
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public class GenericEvent <T > extends ApplicationEvent implements ResolvableTypeProvider { public GenericEvent (T source) { super (source); } @Override public ResolvableType getResolvableType () { return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(getSource())); } @Override public T getSource () { return (T) super .getSource(); } } public class UserEventListener implements ApplicationListener <GenericEvent <User >> { @EventListener public void onUser (User user) { System.out.println("onUser : " + user); } @EventListener public void onUserEvent (GenericEvent<User> event) { System.out.println("onUserEvent : " + event.getSource()); } @Override public void onApplicationEvent (GenericEvent<User> event) { System.out.println("onApplicationEvent : " + event.getSource()); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static void main (String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(UserEventListener.class); context.refresh(); GenericEvent<User> event = new GenericEvent(new User("用户1" )); context.publishEvent(event); context.publishEvent(new User("用户2" )); context.close(); }
针对泛型事件,在通知的时候,可以直接传入 泛型对象,也可以构建GenericEvent
对象。
2.4 异步事件监听 使用 @Async
注解可以快速实现异步调用。当然,需要提前使用 @EnableAsync
,开启异步功能。
1 2 3 4 5 6 7 8 9 @EnableAsync public class MyAsyncEventListener { @EventListener(ContextRefreshedEvent.class) @Async public Boolean ontextRefreshedEvent (ContextRefreshedEvent event) { println(" MyAsyncEventListener : " + event.getClass().getSimpleName()); return true ; } }
也可以实现实现 org.springframework.scheduling.annotation.AsyncConfigurer
自定义异步调用的线程池。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Configuration @EnableAsync public class AopConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor () { ThreadPoolExecutor poolExecutor = ThreadPoolGenerator.newCallerRunSyncQueuePool("AsyncThreadPool" , 20 , 50 ); return poolExecutor; } @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler () { return null ; } }
3 分析 3.1 Spring 事件发布 3.1.1 ApplicationEventMulticaster 注册 ApplicationListener 在org.springframework.context.ApplicationListener
的注释上,ApplicationListener
是依赖java.util.EventListener
的 Observer 设计模式(观察者模式)。并,关联了org.springframework.context.event.ApplicationEventMulticaster
接口。
1 2 3 4 5 6 7 8 9 10 public interface ApplicationEventMulticaster { void addApplicationListener (ApplicationListener<?> listener) ; void addApplicationListenerBean (String listenerBeanName) ; void removeApplicationListener (ApplicationListener<?> listener) ; void removeApplicationListenerBean (String listenerBeanName) ; void removeAllListeners () ; void multicastEvent (ApplicationEvent event) ; void multicastEvent (ApplicationEvent event, @Nullable ResolvableType eventType) ; }
从以上接口看,ApplicationEventMulticaster
的主要职责是:
关联 ApplicationListener
广播 ApplicationEvent
从ApplicationEventMulticaster
的实现类来看,只有一个抽象类org.springframework.context.event.AbstractApplicationEventMulticaster
和唯一实现类org.springframework.context.event.SimpleApplicationEventMulticaster
。
在抽象类AbstractApplicationEventMulticaster
中,你会发现有两个成员变量defaultRetriever
和retrieverCache
。org.springframework.context.event.AbstractApplicationEventMulticaster.ListenerCacheKey
和 org.springframework.context.event.AbstractApplicationEventMulticaster.ListenerRetriever
都是AbstractApplicationEventMulticaster
的内部类。
1 2 3 4 5 6 public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster , BeanClassLoaderAware , BeanFactoryAware { private final ListenerRetriever defaultRetriever = new ListenerRetriever(false ); final Map<ListenerCacheKey, ListenerRetriever> retrieverCache = new ConcurrentHashMap<>(64 ); ...... }
内部类ListenerCacheKey
包含了两个属性,sourceType
和eventType
。
1 2 3 4 5 6 private static final class ListenerCacheKey implements Comparable <ListenerCacheKey > { private final ResolvableType eventType; @Nullable private final Class<?> sourceType; ..... }
内部类ListenerRetriever
包含这ApplicationListener
的Set。
1 2 3 4 5 6 private class ListenerRetriever { public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>(); public final Set<String> applicationListenerBeans = new LinkedHashSet<>(); private final boolean preFiltered; ... }
这时候,就知道AbstractApplicationEventMulticaster#defaultRetriever
维护这所有的ApplicationListener
;AbstractApplicationEventMulticaster#retrieverCache
是以ListenerCacheKey
为key,ListenerRetriever
为Value 的 Map。并且 ListenerRetriever
维护着ApplicationListener
的Set。
就是将defaultRetriever
进行分类,存在在retrieverCache
中。
3.1.2 AbstractApplicationEventMulticaster 广播事件 ApplicationEventMulticaster#multicastEvent(ApplicationEvent)
方法在SimpleApplicationEventMulticaster
中被重写了。
1 2 3 4 5 6 7 8 9 10 11 12 13 @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); } } }
SimpleApplicationEventMulticaster
在广播的时候,会先判断executor
是否为空,为空才同步调用。可以通过SimpleApplicationEventMulticaster#setTaskExecutor
方法初始化。
3.1.3 ApplicationEventMulticaster 与 ApplicationContext 之间的关系 Spring Framework 官方文档提到开发人员可使用ApplicationEventPublisher
发布ApplicationEvent
。
1 2 3 4 5 6 7 @FunctionalInterface public interface ApplicationEventPublisher { default void publishEvent (ApplicationEvent event) { publishEvent((Object) event); } void publishEvent (Object event) ; }
从接口上看,ApplicationEventPublisher
貌似和ApplicationEventMulticaster
没有什么关联。只有发布的接口,没有关联ApplicationListener
的接口。
不过ApplicationEventPublisher
被ApplicationContext
继承,因此,无论哪种ApplicationContext
都具备发布ApplicationEvent
的能力。
要如何得到ApplicationEventPublisher
实例?官方文档提示,实现ApplicationEventPublisherAware
接口。也可以直接使用@Autowired
注解自动导入。
在 Spring Framework 中,Aware Bean 生命周期回调均有ApplicationContextAwareProcessor
处理。
ApplicationEventPublisher
被ApplicationContext
继承,自动注入的ApplicationEventPublisher
实例,就是ApplicationContext
实例。AbstractApplicationContext
完全实现了ApplicationEventPublisher
接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 @Nullable private ApplicationEventMulticaster applicationEventMulticaster;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); } ApplicationEvent 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 { getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); } if (this .parent != null ) { if (this .parent instanceof AbstractApplicationContext) { ((AbstractApplicationContext) this .parent).publishEvent(event, eventType); } else { this .parent.publishEvent(event); } } } ApplicationEventMulticaster getApplicationEventMulticaster () throws IllegalStateException { if (this .applicationEventMulticaster == null ) { throw new IllegalStateException("ApplicationEventMulticaster not initialized - " + "call 'refresh' before multicasting events via the context: " + this ); } return this .applicationEventMulticaster; }
applicationEventMulticaster
属性由initApplicationEventMulticaster()
方法初始化,并且该方法被refresh()
调用。
因此ConfigurableApplicationContext
能够发布事件,管理事件,是复用了ApplicationEventMulticaster
。
总结:
ConfigurableApplicationContext
继承 ApplicationEventPublisher
。
ApplicationEventPublisher
拥有发布ApplicationEvent
的接口。
AbstractApplicationContext
实现 ConfigurableApplicationContext
接口,增加成员变量ApplicationEventMulticaster
,利用ApplicationEventMulticaster
实现ApplicationEventPublisher
的功能。
ApplicationEventMulticaster
负责管理ApplicationListener
。
3.2 Spring 自定义事件 根据官方文档的提示,自定义 Spring 事件需要扩展ApplicationEvent
接口,然后由ApplicationEventPublisher#publishEvent(java.lang.Object)
发布即可。
3.3 Spring 事件监听 Spring 事件监听接口 ApplicationListener
是事件监听的常见手段。在此基础上,Spring 4.2开始引入@EventListener
注解。
3.3.1 ApplicationListener
监听原理 根据上面的内容,以知发布事件,调用的是SimpleApplicationEventMulticaster#multicastEvent(ApplicationEvent)
。并且SimpleApplicationEventMulticaster
可关联Executor
实现异步事件广播。然后,SimpleApplicationEventMulticaster默认采用同步广播。根据ApplicationEvent
具体类型查找匹配的ApplicationListener
列表,然后逐一同步或异步调用ApplicationListener#onApplicationEvent
方法,实现ApplicationListener
的监听。
3.3.2 @EventListener
方法实现原理 从 Spring Framework 4.2 开始,框架层面在 AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry, Object)
方法中增加了@EventListener
方法处理的相关Bean的注册:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public static final String EVENT_LISTENER_PROCESSOR_BEAN_NAME = "org.springframework.context.event.internalEventListenerProcessor" ; public static final String EVENT_LISTENER_FACTORY_BEAN_NAME = "org.springframework.context.event.internalEventListenerFactory" ; public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors ( BeanDefinitionRegistry registry, @Nullable Object source) { ...... if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME)); } if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME)); } return beanDefs; }
其中EventListenerMethodProcessor
是@EventListener
方法的生命周期处理器,而DefaultEventListenerFactory
则是@EventListener
方法与ApplicationListener
适配器的工程类。
EventListenerMethodProcessor
作为SmartInitializingSingleton
接口实现。
3.3.2.1 SmartInitializingSingleton
生命周期回调 1 2 3 public interface SmartInitializingSingleton { void afterSingletonsInstantiated () ; }
通过调用关系可以发现,SmartInitializingSingleton#afterSingletonsInstantiated()
方法将在DefaultListableBeanFactory#preInstantiateSingletons()
方法执行时调用。
同时,从完整的Spring应用上下文生命周期分析,以上preInstantiateSingletons()
方法处于AbstractApplicationContext#finishBeanFactoryInitialization(ConfigurableListableBeanFactory)
调用周期的最后一个操作,并且也接近于refresh()
方法的完成阶段。
3.3.2.2 EventListenerMethodProcessor
的实现原理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Override public void afterSingletonsInstantiated () { List<EventListenerFactory> factories = getEventListenerFactories(); ConfigurableApplicationContext context = getApplicationContext(); String[] beanNames = context.getBeanNamesForType(Object.class); for (String beanName : beanNames) { ...... try { processBean(factories, beanName, type); } ...... } } protected List<EventListenerFactory> getEventListenerFactories () { Map<String, EventListenerFactory> beans = getApplicationContext().getBeansOfType(EventListenerFactory.class); List<EventListenerFactory> factories = new ArrayList<>(beans.values()); AnnotationAwareOrderComparator.sort(factories); return factories; }
按照 afterSingletonsInstantiated()
方法的生命周期,getEventListenerFactories()
方法根据类型在Spring应用上下文中查找所有EventListenerFactory
Bean的操作不会引起过早初始化的问题。
EventListenerMethodProcessor#processBean
方法相对简单,首先从指定Bean类型中超找所有标注@EventListener
的方法,由于AnnotatedElementUtils#findMergedAnnotation
语言的作用,所有方法筛选的规则是仅判断Bean中所有public方法是否标注@EventListener
。
然后,EventListenerMethodProcessor
将候选的@EventListener
方法集合逐一经过EventListenerFactory
实例列表(首参)的匹配。而默认情况下,EventListenerFactory
实例列表仅为DefaultEventListenerFactory
对象,故将@EventListener
方法适配为ApplicationListener
对象。
1 2 3 4 5 6 7 8 9 10 11 public class DefaultEventListenerFactory implements EventListenerFactory , Ordered { ...... public boolean supportsMethod (Method method) { return true ; } @Override public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) { return new ApplicationListenerMethodAdapter(beanName, type, method); } }
因此,@EventListener
方法实现的确与ApplicationListener
有关。
原文链接: https://adeng-wc.github.io/index.html
版权声明: 转载请注明出处.