解决Maven项⽬相互依赖循环依赖双向依赖的问题
很多时候随着项⽬的膨胀,模块会越来越多,如果设计上稍有不慎就会出现模块之间相互依赖的情况。这对于使⽤M aven的⽤户是⽐较痛苦的,因为出现模块之间相互依赖的话在构建的时候就会失败,Maven通常要先编译被依赖的模块,如果出现相互依赖M aven就不知道该怎么办了。下图描述了三个M aven模块相互依赖的场景:
图 1. A、B、C三个模块相互依赖
图中模块C依赖于模块B,模块B依赖于模块A,⽽模块A⼜依赖于模块C,这样就出现了相互依赖情况,如果运⾏m vn compile会出现如下错误:
[INFO] Scanning [ERROR] The projects in the reactor contain a cyclic reference: Edge between 'Ve rtex{label='org.kuuyee.sample:module-C:1.0-SNAPSHOT'}' and 'Vertex{label='org.ku uyee.sample:module-B:1.0-SNAPSHOT'}' introduces to cycle in the graph org.kuuyee .sample:module-B:1.0-SNAPSHOT --> org.kuuyee.sample:module-A:1.0-SNAPSHOT --> or g.kuuyee.sample:module-C:1.0-SNAPSHOT --> org.kuuyee.sample:module-B:1.0-SNAPSHO T -> [Help 1][ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e swit ch.[ERROR] Re-run Maven using the -X switch to enable full debug logging.[ERROR] [ERROR] For more information about the errors and possible solutions, please rea d the following articles: [ERROR] [Help 1] /confluence/display/MAVEN/ProjectCycleEx ception
1. 使⽤b uild-helper-maven-plugin解决相互依赖的问题我的解决办法就是先把相互依赖的模块整合在⼀起,相当于把这些模块合并成⼀个单独的模块统⼀编译,如下图:图
2. 合并A、B、C三个模块为D模块
这样就产⽣了⼀个合并模块D,我们把它当做⼀个辅助构建模块,然后让A、B、C模块都依赖于D模块,这样的话就可以成功编译A、B和C模块,
如下图:图 3. 基于D模块来分别编译A、B、C三个模块
要想把A、B、C三个模块整合在⼀起编译,需要借助b uild-helper-maven-plugin插件,这个插件在M aven构建周期提供⼀些辅助功能,下⾯列出插件的提供的功
能列表: build-helper:add-source:添加更多的构建源码⽬录 build-helper:add-test-source:添加更多的测试源码⽬录 build-helper:add-resource:添加更多的资源⽬录 build-helper:add-test-resource:添加更多的测试资源⽬录 build-helper:attach-artifact:在安装和部署周期附加a rtifacts build-helper:maven-version:添加⼀个指定当前M aven 版本的属性 build-helper:parse-version:添加⼀个指定组件版本的属性 build-helper:released-version:决定当前项⽬的最终版本 build-
helper:remove-project-artifact:从本地资源库中移除项⽬的a rtifacts build-helper:reserve-network-port:Reserve a list of random and unused network ports. 在这⾥我们要⽤到b uild-helper:add-source 这个功能,将模块A 、B 、C 的源码路径加进来。 我们再添加⼀个辅助模块D ,在辅助模块D 中使⽤b uild-helper-maven-plugin 插件,然后让模块A 、B 、C 都依赖于辅助模块D ,模块D 的P OM 模型如下: 例 1. 辅助模块D 的P OM 模型
【转载地址】www.blogjava/kuuyee/archive/2011/06/28/353158.html
maven 处理循环依赖
在多maven ⼯程的项⽬⾥,如果⼯程间存在循环依赖,构建就会报错。本⽂介绍⼀下循环依赖要怎么处理
1、什么是循环依赖 Java 代码
01. <project xmlns="/POM/4.0.0" 02. xmlns:xsi="/2001/XMLSchema-instance" 03. xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd"> 04. <parent> 05. <groupId>org.kuuyee.sample</groupId> 06. <artifactId>sa
mple-parent</artifactId> 07. <version>1.0-SNAPSHOT</version> 08. <relativePath>../../l</relativePath> 09. </parent> 10. <modelVersion>4.0.0</modelVersion> 11. <groupId>org.kuuyee.sample</groupId> 12. <artifactId>module-D</artifactId> 13. <version>1.0-SNAPSHOT</version> 14. <packaging>jar</packaging> 15. <name>module-D</name> 16. <url></url> 17. <properties> 18. <project.build.sourceEncoding> 19. UTF-8 20. </project.build.sourceEncoding> 21. <module.a.src>../../module/module-A/src/main/java</module.a.src> 22. <module.b.src>../../module/module-B/src/main/java</module.b.src> 23. &src>../../module/module-C/src/main/java</src> 24. </properties> 25. <build> 26. <plugins><!-- 解决模块相互依赖,综合所有相互依赖代码统⼀编译 --> 27. <plugin> 28. <groupId&jo</groupId> 29. <artifactId>build-helper-maven-plugin</artifactId> 30. <executions> 31. <execution> 32. <id>add-source</id> 33. <phase>generate-sources</phase> 34. <goals> 35. <goal>add-source</goal> 36. </goals> 37. <configuration> 38. <sources> 39. <source>${module.a.src}</source> 40. <source>${module.b.src}</source> 41.
<source>${src}</source> 42. </sources> 43. </configuration> 44. </execution> 45. </executions> 46. </plugin> 47. </plugins> 48. </build> 49. <dependencies> 50. <dependency> 51. <groupId>junit</groupId> 52. <artifactId>junit</artifactId> 53. <version>3.8.1</version> 54. <scope>test</scope> 55. </dependency> 56. </dependencies> 57. </project>
如果⼯程A依赖⼯程B,⼯程B⼜依赖⼯程A,就会形成循环依赖。或者A依赖B,B依赖C,C依赖A,也是循环依赖
总的来说,在画出⼯程依赖图之后,如果发现⼯程间的依赖连线形成了⼀个有向循环图,则说明有循环依赖的现象
如果循环依赖发⽣在⼯程之间,则会影响构建,因为maven不知道应该先编译哪个⼯程。如果循环依赖发⽣在同⼀个⼯程的模块之间,虽然不影响编译,但是也是⼀种不好的实践,说明模块的设计有问题,应该避免
如果在模块内部,有⼏个类互相调⽤的话,我觉得可能是正常的。⽐如观察者模式⾥⾯,Observer和Observable就是互相依赖的
2、怎么解决循环依赖parse error怎么解决
⽬前知道有2个办法可以解决
第⼀个办法是⽤build-helper-maven-plugin插件来规避。⽐如A依赖B,B依赖C,C依赖A的情况。这个插件提供了⼀种规避措施,即临时地将⼯程A、B、C 合并成⼀个中间⼯程,编译出临时的模块D。然后A、B、C再分别依赖临时模块D进⾏编译
这种⽅法可以解决⽆法构建的问题,但是只是⼀个规避措施,⼯程的依赖关系依然是混乱的
第⼆个办法是通过重构,从根本上消除循环依赖
3、如何重构
⽬前也知道2个重构的思路
第⼀个办法是平移,⽐如A和B互相依赖,那么可以将B依赖A的那部分代码,移动到⼯程B中,这样⼀来,B就不需要继续依赖A,只要A依赖B就可以了,从⽽消除循环依赖
第⼆个办法是下移,⽐如A和B互相依赖,同时它们都依赖C,那么可以将B和A相互依赖的那部分代码,移动到⼯程C⾥,这样⼀来,A和B相互之间都不依赖,只继续依赖C,也可以消除循环依赖
这两种重构⽅式都是可⾏的,具体采⽤哪种⽅式要根据实际情况来判断。不管采取哪种⽅式,都需要对代码进⾏修改,有时候并不是那么容易的
【转载地址】www.kaifajie/kaifa_qita/7063.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论