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) { //業務邏輯 } }