自定义事件发布器

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

第一步:

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

        }
    }
}

输出结果:

相关推荐
Apifox4 分钟前
Apifox CLI + Claude Skills:将接口自动化测试融入研发工作流
前端·后端·测试
亓才孓10 分钟前
[认识异常和错误]java
java·开发语言
码农水水17 分钟前
中国电网Java面试被问:流批一体架构的实现和状态管理
java·c语言·开发语言·面试·职场和发展·架构·kafka
程序员Agions22 分钟前
别再只会 console.log 了!这 15 个 Console 调试技巧,让你的 Debug 效率翻倍
前端·javascript
万邦科技Lafite24 分钟前
阿里巴巴商品详情API返回值:电商精准营销的关键
大数据·数据库·人工智能·电商开放平台
我的div丢了肿么办26 分钟前
vue使用h函数封装dialog组件,以命令的形式使用dialog组件
前端·javascript·vue.js
UIUV27 分钟前
Git 提交规范与全栈AI驱动开发实战:从基础到高级应用
前端·javascript·后端
NEXT0628 分钟前
那个写 width: 33.33% 的前端,终于被 flex: 1 拯救了
前端·css
NEXT0629 分钟前
前端即导演:用纯 CSS3 原力复刻《星球大战》经典开场
前端·css