springboot后端的多模块单体开发针对于模块拆分之新手总结(包含与微服务的对比)
多模块单体架构通过层级模块划分实现开发简化,其中父模块管理依赖,子模块单向传递依赖关系。主模块通过组件扫描整合所有子模块功能,但存在单向依赖限制,导致无法自然双向调用。相比微服务,该架构适合层级业务拆分,但在平行业务拆分时易产生循环依赖问题。测试时需启动相关模块,运行效率受影响。对于复杂双向调用场景,建议采用微服务架构更合适。(149字)
多模块单体这个开发方式,相对微服务来说,开发简单,部署方便,但依赖管理严格。
要说拆分模块,那确实可以拆分,但是却是适合基础模块(common)→ 服务模块(service)→ 控制模块(web)这种类型的模块拆分,更像是爷爷奶奶爸爸妈妈这种长辈关系的模块划分,相当于上下关系,而不是按业务平行功能拆分。
假设父模块分为子模块8个模块。但8个子模块并不会平行,而是先通过<packaging>pom</packaging>来让父模块失效启动,废除父模块启动类,你会发现项目结构当中父模块的源码标注就此消失,再把启动的任务交给一个主模块比如子模块1,父模块只负责管理依赖牵个头而已。

然后pom根据依赖传递性,8给了7,7给了6和5,6给4,5给3,4和3给2,2给1这样,最后1里面看似只包含2,实际上包含了所有其他子模块。启动模块1时,它会通过@【ComponentScan(basePackages = "org.example")】来扫描全体模块,进而实现模块之间的单向调用。
缺点在于,首先不能违反依赖传递性,要避免循环依赖,于是只能单向依赖,1用了2那么2不能直接用1,要通过其他方式来弥补。其次是,越是层级高的模块(尤其是主模块1),要稍微启动测试一下里面的功能,它都要扫描所有模块。
主子模块1,是一个springboot,也是整个项目的springboot。倒是可以同时启动1、2、3,那么此时2、3纯属多余启动,因为1的启动已经因为依赖传递而可以使用2和3的服务了,根本不需要通过2、3的服务器去调用服务。所以所有前端,都使用1的端口号即可(要是用其他端口还得多此一举的去打开这个端口的对应模块)
在这种模式下,此项目的springboot启动器有除了父模块以外的所有,如果是测试单个模块,或同时测试好几个模块,没问题。
但是最后整体运行真正用的只有主模块的启动。原头在于模块之间为了调用,只能通过传递依赖的方式给出服务,这本来应该是比微服务好的地方,毕竟不需要考虑跨域之类的东西,然而单向依赖原则使得这种行为让高层次模块聚集了大量底层次模块,尤其是主模块,故而这下想要启动其他服务器也用不着了,多此一举。
但原本这种情况,也就是让开发时的测试更繁忙一点而已(毕竟【单独测某个模块】的能力没有丧失),也即【虽然微服务也要把测试模块相关的模块打开,但是测试的模块引入的模块越多,压力就越大】,测试任何上层模块都需要加载整个依赖树,即使只测试一个小功能。但对于小项目来说这却并不会造成太大影响,顶多运行慢点。并且最后整体运行也是不打紧的,毕竟微服务也要打开全部服务器,对标这里的主子模块扫描全部子模块。
最最最主要让人崩溃的是,没办法自然双向调用,最多只能进行事件总线这种用异步事件替代同步调用,避免循环依赖,或者是接口下沉与依赖倒置这种将双向依赖的接口提取到公共模块的办法来调整
也就是说,分模块时,最好要按照层次高低来拆解项目业务,低层次业务给低层次模块,只会被人调用,高层次就分给高层次,可以调用别人。如果想要进行业务的平行拆分,按业务功能的平行关系拆分,这样一来,那么必然导致双向调用之处不可避免,自然,就不适合多模块单体开发了。还是用微服务架构比较好
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)