自定义事件发布器

我们如何自己来实现一个事件发布器?

第一步:

定义AbstractApplicationEventMulticaster类实现Spring中的ApplicationEventMulticaster事件发布器接口。先做一个空实现。

java 复制代码
 abstract static class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster {

        @Override
        public void addApplicationListener(ApplicationListener<?> listener) {

        }

        @Override
        public void addApplicationListenerBean(String listenerBeanName) {

        }

        @Override
        public void removeApplicationListener(ApplicationListener<?> listener) {

        }

        @Override
        public void removeApplicationListenerBean(String listenerBeanName) {

        }

        @Override
        public void removeAllListeners() {

        }

        @Override
        public void multicastEvent(ApplicationEvent event) {

        }

        @Override
        public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {

        }
    }

第二步:

定义一个线程池。可以让事件发布以多线程方式实现。

java 复制代码
    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(100);
        return executor;
    }

第三步:

往Spring中注入事件发布器对象,返回我们自定义的事件发布器类型,并只要重写两个主要方法。

java 复制代码
    @Bean
    public ApplicationEventMulticaster applicationEventMulticaster(ConfigurableApplicationContext applicationContext,ThreadPoolTaskExecutor taskExecutor) {
        return new AbstractApplicationEventMulticaster(){
            private List<GenericApplicationListener> listeners = new ArrayList<>();
            @Override
            public void addApplicationListenerBean(String name) {
                //搜集事件监听器
                ApplicationListener listener = applicationContext.getBean(name, ApplicationListener.class);
                System.out.println(name);
                ResolvableType type = ResolvableType.forClass(listener.getClass()).getInterfaces()[0].getGeneric();
                System.out.println(type);
                //包装原始的事件监听器,变为支持类型检查的事件监听器
                GenericApplicationListener listener1 = new GenericApplicationListener() {
                    @Override
                    public void onApplicationEvent(ApplicationEvent event) {
                        listener.onApplicationEvent(event);
                    }
                    //是否支持该事件类型
                    @Override
                    public boolean supportsEventType(ResolvableType eventType) {
                        return type.isAssignableFrom(eventType);
                    }
                };
                listeners.add(listener1);
            }
            @Override
            public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
                for (GenericApplicationListener listener : listeners) {
                    if (listener.supportsEventType(ResolvableType.forClass(event.getClass()))) {
                       taskExecutor.submit(() -> {
                           listener.onApplicationEvent(event);
                       });
                    }
                }
            }
        };
    }

重写方法的处理:

1.addApplicationListenerBean方法

springBoot启动过程中会往容器中添加所有的监听器,我们可以拿到所有监听器。但是我们需使用泛型监听器类对对原始获取的监听器类进行包装,因为里面可以提供一个判断事件类型的方法,方便后续对事件类型进行处理。

java 复制代码
public void addApplicationListenerBean(String name) {
                //搜集事件监听器
                ApplicationListener listener = applicationContext.getBean(name, ApplicationListener.class);
                System.out.println(name);
                ResolvableType type = ResolvableType.forClass(listener.getClass()).getInterfaces()[0].getGeneric();
                System.out.println(type);
                //包装原始的事件监听器,变为支持类型检查的事件监听器
                GenericApplicationListener listener1 = new GenericApplicationListener() {
                    @Override
                    public void onApplicationEvent(ApplicationEvent event) {
                        listener.onApplicationEvent(event);
                    }
                    //是否支持该事件类型
                    @Override
                    public boolean supportsEventType(ResolvableType eventType) {
                        return type.isAssignableFrom(eventType);
                    }
                };
                listeners.add(listener1);
            }

2.multicastEvent方法

拿到所有包装后的泛型类型的事件监听器,并调用判断事件类型的方法对真实的事件做判断,如果满足条件使用线程池发布事件。

java 复制代码
            @Override
            public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
                for (GenericApplicationListener listener : listeners) {
                    if (listener.supportsEventType(ResolvableType.forClass(event.getClass()))) {
                       taskExecutor.submit(() -> {
                           listener.onApplicationEvent(event);
                       });
                    }
                }
            }

第四步:

总体实现代码如下:

java 复制代码
@Configuration
public class TestPublishe {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestPublishe.class);
        context.getBean(MyService.class).doBusiness();
        context.close();
    }

    static class MyEvent extends ApplicationEvent {
        public MyEvent(Object source) {
            super(source);
        }
    }

    @Component
    static class MyService  {
        private static final Logger log = LoggerFactory.getLogger(TestPublishe.class);
        @Autowired
        private ApplicationEventPublisher publisher;

        public void doBusiness() {
            log.debug("主线业务");
            publisher.publishEvent(new MyEvent("MyService.doBusiness()"));
        }
    }

    @Component
    static class SmsService implements ApplicationListener<MyEvent> {
        private static final Logger log = LoggerFactory.getLogger(SmsService.class);

        @Override
        public void onApplicationEvent(MyEvent event) {
            log.debug("发送短信");
        }
    }

    @Component
    static class EmailService implements ApplicationListener<MyEvent> {
        private static final Logger log = LoggerFactory.getLogger(EmailService.class);

        @Override
        public void onApplicationEvent(MyEvent event) {
            log.debug("发送邮件");
        }
    }
    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(100);
        return executor;
    }
    @Bean
    public ApplicationEventMulticaster applicationEventMulticaster(ConfigurableApplicationContext applicationContext,ThreadPoolTaskExecutor taskExecutor) {
        return new AbstractApplicationEventMulticaster(){
            private List<GenericApplicationListener> listeners = new ArrayList<>();
            @Override
            public void addApplicationListenerBean(String name) {
                //搜集事件监听器
                ApplicationListener listener = applicationContext.getBean(name, ApplicationListener.class);
                System.out.println(name);
                ResolvableType type = ResolvableType.forClass(listener.getClass()).getInterfaces()[0].getGeneric();
                System.out.println(type);
                //包装原始的事件监听器,变为支持类型检查的事件监听器
                GenericApplicationListener listener1 = new GenericApplicationListener() {
                    @Override
                    public void onApplicationEvent(ApplicationEvent event) {
                        listener.onApplicationEvent(event);
                    }
                    //是否支持该事件类型
                    @Override
                    public boolean supportsEventType(ResolvableType eventType) {
                        return type.isAssignableFrom(eventType);
                    }
                };
                listeners.add(listener1);
            }
            @Override
            public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
                for (GenericApplicationListener listener : listeners) {
                    if (listener.supportsEventType(ResolvableType.forClass(event.getClass()))) {
                       taskExecutor.submit(() -> {
                           listener.onApplicationEvent(event);
                       });
                    }
                }
            }
        };
    }
    abstract static class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster {

        @Override
        public void addApplicationListener(ApplicationListener<?> listener) {

        }

        @Override
        public void addApplicationListenerBean(String listenerBeanName) {

        }

        @Override
        public void removeApplicationListener(ApplicationListener<?> listener) {

        }

        @Override
        public void removeApplicationListenerBean(String listenerBeanName) {

        }

        @Override
        public void removeAllListeners() {

        }

        @Override
        public void multicastEvent(ApplicationEvent event) {

        }

        @Override
        public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {

        }
    }
}

输出结果:

相关推荐
恋猫de小郭4 分钟前
Flutter A2UI 深度解析,它是怎么提供动态生产力的,然后为什么 A2UI 不只是 Flutter
android·前端·flutter
snow@li7 分钟前
服务器运维:Alibaba Cloud Linux 4 LTS・Vue前端 Java 后端 K3S 部署 CICD 目录规范清单
linux·前端·vue.js
百变梦仔11 分钟前
Codex 启动回复合格后,我会用三类证据验收前端改动
前端·github
the局外人13 分钟前
别让 Codex 一口气写完整个前端:5 组 Skills,把页面、逻辑、测试和构建拆清楚
前端·人工智能·agent
honkun616 分钟前
vue 表格组件 vxe-table 实实现专业记账凭证编辑表格与自动汇总
前端·javascript·vue.js
xieliyu.16 分钟前
计算机网络|数据链路层详解:MAC 地址、交换机、ARP 协议、CRC 校验
java·网络·笔记·计算机网络·java-ee
SimonKing21 分钟前
手机投屏到电脑,不用装任何 App,这个开源工具免费搞定:QtScrcpy
java·后端·程序员
前端snow23 分钟前
ai agent ---nest+langchain实现SSE推送信息
前端
IMPYLH24 分钟前
HTML 的 <nav> 元素
前端·html