自定义事件发布器

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

第一步:

定义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) {

        }
    }
}

输出结果:

相关推荐
程序员徐师兄13 分钟前
Windows JDK11 下载安装教程,适合新手
java·windows·jdk11 下载安装·jdk11 下载教程
fanruitian14 分钟前
uniapp android开发 测试板本与发行版本
前端·javascript·uni-app
rayufo17 分钟前
【工具】列出指定文件夹下所有的目录和文件
开发语言·前端·python
RANCE_atttackkk21 分钟前
[Java]实现使用邮箱找回密码的功能
java·开发语言·前端·spring boot·intellij-idea·idea
五岳1 小时前
DTS按业务场景批量迁移阿里云MySQL表实战(下):迁移管理平台设计与实现
java·应用·dts
一起养小猫1 小时前
Flutter for OpenHarmony 实战:记账应用数据统计与可视化
开发语言·jvm·数据库·flutter·信息可视化·harmonyos
世界尽头与你1 小时前
(修复方案)CVE-2023-22047: Oracle PeopleSoft Enterprise PeopleTools 未授权访问漏洞
数据库·安全·oracle·渗透测试
韩立学长1 小时前
【开题答辩实录分享】以《智能大学宿舍管理系统的设计与实现》为例进行选题答辩实录分享
数据库·spring boot·后端
zhougl9961 小时前
Java 所有关键字及规范分类
java·开发语言
Python 老手1 小时前
Python while 循环 极简核心讲解
java·python·算法