当前位置: 首页 > news >正文

自定义事件发布器

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

第一步:

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

 abstract static class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster {@Overridepublic void addApplicationListener(ApplicationListener<?> listener) {}@Overridepublic void addApplicationListenerBean(String listenerBeanName) {}@Overridepublic void removeApplicationListener(ApplicationListener<?> listener) {}@Overridepublic void removeApplicationListenerBean(String listenerBeanName) {}@Overridepublic void removeAllListeners() {}@Overridepublic void multicastEvent(ApplicationEvent event) {}@Overridepublic void multicastEvent(ApplicationEvent event, ResolvableType eventType) {}}

第二步:

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

    @Beanpublic ThreadPoolTaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10);executor.setMaxPoolSize(20);executor.setQueueCapacity(100);return executor;}

第三步:

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

    @Beanpublic ApplicationEventMulticaster applicationEventMulticaster(ConfigurableApplicationContext applicationContext,ThreadPoolTaskExecutor taskExecutor) {return new AbstractApplicationEventMulticaster(){private List<GenericApplicationListener> listeners = new ArrayList<>();@Overridepublic 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() {@Overridepublic void onApplicationEvent(ApplicationEvent event) {listener.onApplicationEvent(event);}//是否支持该事件类型@Overridepublic boolean supportsEventType(ResolvableType eventType) {return type.isAssignableFrom(eventType);}};listeners.add(listener1);}@Overridepublic 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启动过程中会往容器中添加所有的监听器,我们可以拿到所有监听器。但是我们需使用泛型监听器类对对原始获取的监听器类进行包装,因为里面可以提供一个判断事件类型的方法,方便后续对事件类型进行处理。

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() {@Overridepublic void onApplicationEvent(ApplicationEvent event) {listener.onApplicationEvent(event);}//是否支持该事件类型@Overridepublic boolean supportsEventType(ResolvableType eventType) {return type.isAssignableFrom(eventType);}};listeners.add(listener1);}

2.multicastEvent方法

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

            @Overridepublic void multicastEvent(ApplicationEvent event, ResolvableType eventType) {for (GenericApplicationListener listener : listeners) {if (listener.supportsEventType(ResolvableType.forClass(event.getClass()))) {taskExecutor.submit(() -> {listener.onApplicationEvent(event);});}}}

第四步:

          总体实现代码如下:

@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);}}@Componentstatic class MyService  {private static final Logger log = LoggerFactory.getLogger(TestPublishe.class);@Autowiredprivate ApplicationEventPublisher publisher;public void doBusiness() {log.debug("主线业务");publisher.publishEvent(new MyEvent("MyService.doBusiness()"));}}@Componentstatic class SmsService implements ApplicationListener<MyEvent> {private static final Logger log = LoggerFactory.getLogger(SmsService.class);@Overridepublic void onApplicationEvent(MyEvent event) {log.debug("发送短信");}}@Componentstatic class EmailService implements ApplicationListener<MyEvent> {private static final Logger log = LoggerFactory.getLogger(EmailService.class);@Overridepublic void onApplicationEvent(MyEvent event) {log.debug("发送邮件");}}@Beanpublic ThreadPoolTaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10);executor.setMaxPoolSize(20);executor.setQueueCapacity(100);return executor;}@Beanpublic ApplicationEventMulticaster applicationEventMulticaster(ConfigurableApplicationContext applicationContext,ThreadPoolTaskExecutor taskExecutor) {return new AbstractApplicationEventMulticaster(){private List<GenericApplicationListener> listeners = new ArrayList<>();@Overridepublic 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() {@Overridepublic void onApplicationEvent(ApplicationEvent event) {listener.onApplicationEvent(event);}//是否支持该事件类型@Overridepublic boolean supportsEventType(ResolvableType eventType) {return type.isAssignableFrom(eventType);}};listeners.add(listener1);}@Overridepublic 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 {@Overridepublic void addApplicationListener(ApplicationListener<?> listener) {}@Overridepublic void addApplicationListenerBean(String listenerBeanName) {}@Overridepublic void removeApplicationListener(ApplicationListener<?> listener) {}@Overridepublic void removeApplicationListenerBean(String listenerBeanName) {}@Overridepublic void removeAllListeners() {}@Overridepublic void multicastEvent(ApplicationEvent event) {}@Overridepublic void multicastEvent(ApplicationEvent event, ResolvableType eventType) {}}
}

输出结果:


文章转载自:

http://ksz6f8Pt.Lnyds.cn
http://iHgZmEGl.Lnyds.cn
http://bYvICxtB.Lnyds.cn
http://rZMWy48g.Lnyds.cn
http://LgKYOvMu.Lnyds.cn
http://WPZYRsth.Lnyds.cn
http://QvFGTK05.Lnyds.cn
http://OFNZsgFc.Lnyds.cn
http://IpJJv2WL.Lnyds.cn
http://nwj557Fu.Lnyds.cn
http://tvKvYb9W.Lnyds.cn
http://gFWbyxRL.Lnyds.cn
http://wYF8QUdM.Lnyds.cn
http://38JGePA6.Lnyds.cn
http://Cbb5KuFM.Lnyds.cn
http://9EOkh2Dh.Lnyds.cn
http://aK1gZeOI.Lnyds.cn
http://ue92mMeK.Lnyds.cn
http://5tKZgrSf.Lnyds.cn
http://xYhneVSN.Lnyds.cn
http://2WZ0P6iC.Lnyds.cn
http://7jN1Pbnj.Lnyds.cn
http://NlrBTGt1.Lnyds.cn
http://2diX9B0b.Lnyds.cn
http://6ZU3MwV0.Lnyds.cn
http://O67FOLnL.Lnyds.cn
http://CBD4byjG.Lnyds.cn
http://ktDRuXKu.Lnyds.cn
http://s3q8jVOa.Lnyds.cn
http://0M28XWXp.Lnyds.cn
http://www.dtcms.com/a/376673.html

相关文章:

  • 零基础学AI大模型之从0到1调用大模型API
  • vue3:调用接口的时候怎么只传递一个数组进去,得到一个key-value数据
  • Transformer 训不动:注意力 Mask 用反 / 广播错位
  • Prometheus部署监控实战
  • vue3引入海康监控视频组件并实现非分屏需求一个页面同时预览多个监控视频(2)
  • AGV 智能车驱动仓储效率提升:应用场景,智慧物流自动化实践指南
  • 【全栈实战】Elasticsearch 8.15.2 高可用集群部署与AI搜索全特性指南
  • Django REST Framework 构建安卓应用后端API:从开发到部署的完整实战指南
  • neo4j数据库创建范例(SQL文)
  • [rStar] docs | 求解协调器
  • WPF迁移avalonia之触发器
  • 【WPF+Prism】日常开发问题总结
  • 差异基因分析实战:手把手教你用R语言找到关键基因
  • 金融数据库--3Baostock
  • 【ICLR 2023】可逆列网络(RevCol)
  • Java SE 与常用框架
  • Web安全基石:深入理解与防御越权问题
  • 手写MyBatis第58弹:如何优雅输出可执行的SQL语句--深入理解MyBatis日志机制:
  • 2025流量新逻辑:AI × IP × 联盟|创客匠人
  • UGUI源码剖析(15):Slider的运行时逻辑与编辑器实现
  • 第 16 篇:服务网格的未来 - Ambient Mesh, eBPF 与 Gateway API
  • 基于Matlab不同作战类型下兵力动力学模型的构建与稳定性分析
  • 基于AIS动态数据与AI结合得经纬度标示算法
  • 第5章 HTTPS与安全配置
  • ZYNQ PL端采集AD7606数据与ARM端QT显示实战指南
  • 头条号采集软件V12.2主要更新内容
  • 吱吱企业即时通讯平衡企业通讯安全与协作,提升企业办公效率
  • 中线安防保护器,也叫终端电气综合治理保护设备为现代生活筑起安全防线
  • 从零实现一个简化版string 类 —— 深入理解std::string的底层设计
  • 记一次Cloudflare五秒盾的研究