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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章