自定义事件发布器

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

第一步:

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

        }
    }
}

输出结果:

相关推荐
q***071436 分钟前
Spring Boot 多数据源解决方案:dynamic-datasource-spring-boot-starter 的奥秘(上)
java·spring boot·后端
q***498644 分钟前
Spring Boot 3.4 正式发布,结构化日志!
java·spring boot·后端
西洼工作室2 小时前
项目环境变量配置全攻略
前端
阿珊和她的猫2 小时前
Webpack 优化:构建速度与包体积的双重提升
前端·webpack·node.js
阿珊和她的猫2 小时前
Webpack 打包体积优化:让应用更轻量、更高效
前端·webpack·状态模式
im_AMBER2 小时前
Vite + React 项目启动深度踩坑指南
前端·学习·react.js·前端框架
Hammer Ray2 小时前
前端开发基础概念(React)
前端·react.js·前端框架
沐浴露z3 小时前
【微服务】基本概念介绍
java·微服务
数据皮皮侠3 小时前
区县政府税务数据分析能力建设DID(2007-2025)
大数据·数据库·人工智能·信息可视化·微信开放平台
Z3r4y4 小时前
【代码审计】RuoYi-4.7.3&4.7.8 定时任务RCE 漏洞分析
java·web安全·ruoyi·代码审计