巧用消息驱动解耦功能模块之间的复杂关系

        不知各位看官遇到开发大型系统的时候,往往功能模块之间都有理不清的复杂关系,例如MES中的生产进度,ERP中的物品流向,单据的处理流程变更,库存的变更等等,很多时候,都是需要模块之间协作才能更好的简化数据处理,靠关联性查询来找结果,难度很大的,说白了就是要把复杂的关系数据,冗余到相关各相关模块中,把错综复杂的关系数据砍断。

        做系统的时候,设计功能的时候,相互都存在一定方向的调用关系的,例如员工模块是不会去调用业务模块的,例如要删除一个员工,要查询是否与业务数据产生了关联关系,如果删掉了,就会导致查询时候缺失了这个员工的信息,可能影响到部门的业绩数据。那么怎么才能判断是否可以删除员工数据呢?

        消息驱动机制,可以简单理解成一个大喇叭,发生了什么时候,喊一下,全场都听到了,至于听到之后,是否要处理,那就是自己的事情了。注意,发出去的消息必须是单向的,不能设计成API的等待返回模式。

        看了很多第三方开发的框架,都有类似MessageCenter的类,但是都有一个特点,不知道是不是我理解有问题了,先说说。发布消息基本都是一个模式:

        Send<T>(string topic,T data);

        订阅的一方基本都是

        MessageCenter.Consume<T>(string topic,Action<T> action);

        订阅的时候,要执行这么个订阅方法,否则就不能收到消息。但是,如果一个模块没有启动过,是不是可以认为,这个模块就会丢失消息了呢?起码我是这么认为的。

        其实我是不希望程序员知道有个MessageCenter类的,总感觉给程序员知道太多,可控性就约差。于是,就专门做了一个插件,起了个简单的名字,IMHelper.这里封装了发布和订阅的方法,原理其实很简单,就是比传统的MessageCenter多了一个启动器,让我慢慢道来。

        发布消息都没有问题,主要是订阅这部分,具体使用如下:

       

[IMConsume("StoreChanged")]
public void DoStoreChanged(StoreEventArgs args)
{//处理库存变化后的消息
}

在程序启动的时候,加载一个消息转发类,命名为IMStarter,例如在Framework中,放到Application_Start()事件中加载。这个类一旦启动,就收集带有IMConsume标签的类和方法,产生一个List<ConsumeInfo>列表, 找这么个列表,当然通过反射实现了,不一一说明了。

        public class consumeInfo

        {

                public MethodInfo method {get;set;}

                public string Topic{get;set;}

        }

        注意,同一个主题可能会有多个方法订阅的,所以不能做成key\value的数据结构。

        IMStarter另外一个功能就是就是接收所有发送出来的消息,然后根据topic来寻找到对应的方法,然后把消息传递到方法中:MethodInfo.Invoke(),由于是单向的,发布一方是不理会返回结果,这里完全可以使用线程来加快处理方法:

        Task.Run(()=>{method.Invoke(....)});

        其实之前也写过类似的内容,只不过是微服务之间的通知,原理都是一样的,一个是从MQ中接收消息然后转发,一个是从内存中接收消息,然后转发。

        这样使用消息驱动的好处就是,当某一个模块去掉了,也不影响现有模块的运行,设置一个订阅者都没有也没有关系,对于日后项目的迁移或者变更,大大降低了代码修改的麻烦事,还是坚持面向对象的原则,自己的事情自己干,不要总想着伸手要数据。不要想着偷懒实现功能就算了,否则日后的维护难度就大大增加。

        用消息驱动,还为插件化开发提供了非常便利的解决方案,甚至动态增加一个库文件,系统也能顺利调用并正确运行,系统就具有了很好的扩展性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/66518.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

字符型注入([SWPUCTF 2021 新生赛]easy_sql)

拿到题目&#xff0c;查看源码&#xff0c;可知是要输入参数wllm。 输入参数/?wllm1&#xff0c;得到会显 继续输入参数/?wllm1&#xff0c;报错&#xff0c;确定为字符型漏洞 1.查看字段列表&#xff0c;发现在字段4报错&#xff0c;确定为3列 ?wllm-1 order by 3-- ?wl…

leetcode做题笔记118. 杨辉三角

给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 思路一&#xff1a;动态规划 int** generate(int numRows, int* returnSize, int** returnColumnSizes){int **returnnum(int **)…

QT DAY 2

window.cpp #include "window.h" #include<QDebug> #include<QIcon> Window::Window(QWidget *parent) //构造函数的定义: QWidget(parent) //显性调用父类的构造函数 {//this->resize(430,330);this->resize(QSize(800,600));// this…

数据结构——单调栈

前导&#xff1a; 队列&#xff0c;栈&#xff0c;前面的链接是对普通的栈&#xff0c;和普通的队列的一个讲解&#xff0c;如果没有对普通的栈和队列不了解的小伙伴可以先看看前面链接中的讲解&#xff1b; 什么是单调&#xff0c;一个序列呈递增或者递减&#xff0c;并且没有…

Spring-Kafka生产者源码分析

文章目录 概要初始化消息发送小结 概要 本文主要概括Spring Kafka生产者发送消息的主流程 代码准备&#xff1a; SpringBoot项目中maven填加以下依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent&…

Flink提交jar出现错误RestHandlerException: No jobs included in application.

今天打包一个flink的maven工程为jar&#xff0c;通过flink webUI提交&#xff0c;发现居然报错。 如上图所示&#xff0c;提示错误为&#xff1a; Server Response Message: org.apache.flink.runtime.rest.handler.RestHandlerException: No jobs included in application. …

Java 线程池概念总结(thread pool)

一、池化思想的应用 池化思想是一种常见软件设计和优化技术。以下是几个常见池化思想应用场景&#xff1a; 线程池&#xff1a;线程池是池化思想一个典型应用。通过预先创建一组线程并将它们置于就绪状态&#xff0c;以复用线程减少线程创建和销毁的开销&#xff0c;并提高系统…

Auto-GPT 学习笔记

Auto-GPT 学习笔记 Auto-GPT 简介 Auto-GPT 是一个基于 GPT-4 的自主智能体实验项目。它展示了大规模语言模型的规划、记忆和工具使用能力。Auto-GPT 的目标是实现一个完全自主的 AI 代理。GitHub 仓库 Auto-GPT 核心模块 规划(Planning) 使用强化学习策略进行多跳思考。通…

两种动态代理比较(补充),进程通信方式总结

jdk和CGLib动态代理: jdk动态代理&#xff1a; java提供的动态代理技术&#xff1b; spring aop默认采用的方式&#xff1b; 只能对实现了至少一个接口的类生成代理对象&#xff1b; CGLib动态代理&#xff1a; 采用底层字节码技术&#xff1b; 目标对象没有实现接口时采…

Nginx特性应用及载装

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。其特点是占有内存少&#xff0c;并发能力强&#xff0c;事实上nginx的并发能力在同类型的网页服务器中表现较好&#xff0c;中国大陆使用nginx的网站有&#xff1a;网易、腾讯、阿里等。 …

文字识别的

对于 PDF 提取文字&#xff0c;Tesseract OCR 是一个常用的工具。你可以使用 Tesseract OCR 的 Java API 来实现。以下是一个使用 Tesseract OCR 提取 PDF 文档文字的简单示例代码&#xff1a; import net.sourceforge.tess4j.Tesseract; import net.sourceforge.tess4j.Tesse…

MyBatis-Plus —— 初窥门径

前言 在前面的文章中荔枝梳理了MyBatis及相关的操作&#xff0c;作为MyBatis的增强工具&#xff0c;MyBatis-Plus无需再在xml中写sql语句&#xff0c;在这篇文章中荔枝将梳理MyBatis-Plus的基础知识并基于SpringBoot梳理MyBatis-Plus给出的两个接口&#xff1a;BaseMapper和ISe…

对象模型和this指针(个人学习笔记黑马学习)

1、成员变量和成员函数 #include <iostream> using namespace std; #include <string>//成员变量和成员函数分开存储class Person {int m_A;//非静态成员变量 属于类的对象上的static int m_B;//静态成员变量 不属于类的对象上void func() {} //非静态成员函数 不…

LeetCode 1921. Eliminate Maximum Number of Monsters【贪心,计数排序】1527

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

供应链 | 顶会CIKM论文精读:面向大规模三维装箱问题的数据驱动树形搜索算法

论文解读&#xff1a;丁建辉&#xff0c;李明哲&#xff0c;赵艳蓉&#xff0c;孙楚天 编者按 本次解读的文章发表于CCF-B类会议30th ACM International Conference on Information and Knowledge Management。摘要总结如下&#xff1a; 3维装箱问题&#xff08;3D-BPP&#…

Redis的缓存穿透,缓存击穿,缓存雪崩

1. 缓存穿透 什么是缓存穿透&#xff1f; 缓存穿透说简单点就是大量请求的 key 是不合理的&#xff0c;根本不存在于缓存中&#xff0c;也不存在于数据库中 。这就导致这些请求直接到了数据库上&#xff0c;根本没有经过缓存这一层&#xff0c;对数据库造成了巨大的压力&…

雪花算法生成id分析与实践

目录 1 什么是雪花算法&#xff1f; 结构 优点 缺点 2 在java中使用 使用注意&#xff1a; 测试代码 效果 1 什么是雪花算法&#xff1f; witter的雪花算法&#xff08;Snowflake Algorithm&#xff09;。雪花ID是一种分布式唯一ID生成算法&#xff0c;旨在解决分布式…

业绩走低,毛利率下滑,海外市场能否成为极米科技救命稻草?

撰稿|行星 来源|贝多财经 8月30日&#xff0c;成都极米科技股份有限公司&#xff08;SH:688696&#xff0c;下称“极米科技”&#xff09;发布2023年半年度业绩报告。财报显示&#xff0c;极米科技2023年上半年的业绩出现了大幅下滑&#xff0c;其中收入同比减少两成&#xf…

代码随想录二刷day06

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、力扣242. 有效的字母异位词二、力扣349. 两个数组的交集三、力扣202. 快乐数四、力扣1两数之和 前言 一、力扣242. 有效的字母异位词 class Solution {pub…

数学建模-点评笔记 9月3日

1.摘要&#xff1a;关键方法和结论&#xff08;精炼的语言&#xff09;要说明&#xff0c;方法的合理性和意义也可以说明。 评委先通过摘要筛选&#xff08;第一轮&#xff09; 2.时间序列找异常值除了3西格玛还有针对时间序列更合适寻找的方法 3.模型的优缺点要写的详细一点…