spring 事件监听同时支持同步事件及异步事件
spring的事件监听机制这里就不再赘述了,不清楚的可以自行google,我们知道,事件发布是依靠调用实现了ApplicationEventPublisher接口类的publishEvent方法进行发布事件,而publishEvent 方法又是通过调用实现了ApplicationEventMulticaster接口的类的multicastEvent方法进行事件的广播的,ApplicationEventMulticaster中保存了所有的实现了ApplicationListener接口的监听器,我们看一下spring内部实现ApplicationEventMulticaster接口的一个广播器SimpleApplicationEventMulticaster的源码
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster { private Executor taskExecutor; public SimpleApplicationEventMulticaster() { } public SimpleApplicationEventMulticaster(BeanFactory beanFactory) { this.setBeanFactory(beanFactory); } public void setTaskExecutor(Executor taskExecutor) { this.taskExecutor = taskExecutor; } protected Executor getTaskExecutor() { return this.taskExecutor; } public void multicastEvent(final ApplicationEvent event) { Iterator i$ = this.getApplicationListeners(event).iterator(); while(i$.hasNext()) { final ApplicationListener listener = (ApplicationListener)i$.next(); Executor executor = this.getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { public void run() { listener.onApplicationEvent(event); } }); } else { listener.onApplicationEvent(event); } } } }
可以看到,异步事件通知主要依靠SimpleApplicationEventMulticaster 类中的Executor去实现的,如果这个变量不配置的话默认事件通知是同步的, 否则就是异步通知了,要实现同时支持同步通知和异步通知就得从这里下手;
我的实现方式是为每个监听方法加个自定义注解,然后在multicastEvent方法中获取对应监听器上的注解,根据注解去决定是同步通知还是异步通知,这样就可以同时支持了,废话不多说,直接看代码
/** * event listener 专用注解,只能加在实现了ApplicationListener 的onApplicationEvent方法上 * 用来标识是同步监听还是异步监听 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface EventType { EventTypeEnum value() default EventTypeEnum.ASYNC; }
/** * @Description: 事件监听枚举类 * @Author Mr.huang * @Date 2020/3/20 0020 * @Version V1.0 **/ public enum EventTypeEnum { ASYNC, //异步 SYNC; //同步 }
/** * @Description: 事件广播基础类,支持自定义注解实现同步或异步的事件监听 * @Author Mr.huang * @Date 2020/3/20 0020 * @Version V1.0 **/ public class BaseApplicationEventMulticaster extends SimpleApplicationEventMulticaster { private static Logger log = LoggerFactory.getLogger(BaseApplicationEventMulticaster.class); @SuppressWarnings("unchecked") public void multicastEvent(final ApplicationEvent event) { //默认异步 EventTypeEnum defaultEventType = EventTypeEnum.ASYNC; for (final ApplicationListener listener : getApplicationListeners(event)) { try { Class listenerClass = Class.forName(listener.getClass().getName()); if(listenerClass!=null){ Method onApplicationEventMethod = listenerClass.getMethod("onApplicationEvent",ApplicationEvent.class); if(onApplicationEventMethod.isAnnotationPresent(EventType.class)){ //获取该元素上指定类型的注解 EventType eventMethodAnnotation = onApplicationEventMethod.getAnnotation(EventType.class); defaultEventType = eventMethodAnnotation.value(); } } } catch (Exception e) { log.error("获取监听类实例出错~"); } Executor executor = getTaskExecutor(); if (executor != null&&defaultEventType==EventTypeEnum.ASYNC) { executor.execute(new Runnable() { public void run() { listener.onApplicationEvent(event); } }); } else { listener.onApplicationEvent(event); } } } }
最后在实现了ApplicationListener接口类中的onApplicationEvent方法上加上注解即可
/** * @Description: TODO * @Author Mr.huang * @Date 2020/3/21 0021 * @Version V1.0 **/ public class UserChargeService implements ApplicationListener<UserChargeEvent> { @EventType(value = EventTypeEnum.ASYNC) @Override public void onApplicationEvent(UserChargeEvent userChargeEvent) { //业务逻辑 } }
智者,寡言而多行