很多时候随着项目的膨胀,模块会越来越多,如果设计上 稍有不慎就会出现模块之间相互依赖的情况。这对于使用Maven的用户是比较痛苦的,因为出现模块之间相互依赖的话在构建的时候就会失败,Maven通常要先编译被依赖的模块,如果出现相互依赖Maven就不知道该怎么办了。下图描述了三个Maven模块相互依赖的场景:
图 1. A、B、C三个模块相互依赖
图中模块C依赖于模块B,模块B依赖于模块A,而模块A又依赖于模块C,这样就出现了相互依赖情况,如果运行mvn compile会出现如下错误:
[INFO] Scanning for projects... [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] http://cwiki.apache.org/confluence/display/MAVEN/ProjectCycleEx ception
1. 使用build-helper-maven-plugin解决相互依赖的问题我的解决办法就是先把相互依赖的模块整合在一起,相当于把这些模块合并成一个单独的模块统一编译,
如下图:图 2. 合并A、B、C三个模块为D模块
这样就产生了一个合并模块D,我们把它当做一个辅助构建模块,然后让A、B、C模块都依赖于D模块,这样的话就可以成功编译A、B和C模块,
如下图: 图 3. 基于D模块来分别编译A、B、C三个模块
要想把A、B、C三个模块整合在一起编译,需要借助build-helper-maven-plugin插件,这个插件在Maven构建周期提供一些辅助功能,下面列出插件的提供的功能列表: build-helper:add-source:添加更多的构建源码目录 build-helper:add-test-source:添加更多的测试源码目录 build-helper:add-resource:添加更多的资源目录 build-helper:add-test-resource:添加更多的测试资源目录 build-helper:attach-artifact:在安装和部署周期附加artifacts build-helper:maven-version:添加一个指定当前Maven版本的属性 build-helper:parse-version:添加一个指定组件版本的属性 build-helper:released-version:决定当前项目的最终版本 build-helper:remove-project-artifact:从本地资源库中移除项目的artifacts build-helper:reserve-network-port:Reserve a list of random and unused network ports. 在这里我们要用到build-helper:add-source这个功能,将模块A、B、C的源码路径加进来。 我们再添加一个辅助模块D,在辅助模块D中使用build-helper-maven-plugin插件,然后让模块A、B、C都依赖于辅助模块D,模块D的POM模型如下: 例 1. 辅助模块D的POM模型
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <groupId>org.kuuyee.sample</groupId>
- <artifactId>sample-parent</artifactId>
- <version>1.0-SNAPSHOT</version>
- <relativePath>../../pom.xml</relativePath>
- </parent>
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.kuuyee.sample</groupId>
- <artifactId>module-D</artifactId>
- <version>1.0-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>module-D</name>
- <url>http://maven.apache.org</url>
- <properties>
- <project.build.sourceEncoding>
- UTF-8
- </project.build.sourceEncoding>
- <module.a.src>../../module/module-A/src/main/java</module.a.src>
- <module.b.src>../../module/module-B/src/main/java</module.b.src>
- <module.c.src>../../module/module-C/src/main/java</module.c.src>
- </properties>
- <build>
- <plugins><!-- 解决模块相互依赖,综合所有相互依赖代码统一编译 -->
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>add-source</id>
- <phase>generate-sources</phase>
- <goals>
- <goal>add-source</goal>
- </goals>
- <configuration>
- <sources>
- <source>${module.a.src}</source>
- <source>${module.b.src}</source>
- <source>${module.c.src}</source>
- </sources>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
- </project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>org.kuuyee.sample</groupId> <artifactId>sample-parent</artifactId> <version>1.0-SNAPSHOT</version> <relativePath>../../pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <groupId>org.kuuyee.sample</groupId> <artifactId>module-D</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>module-D</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding> <module.a.src>../../module/module-A/src/main/java</module.a.src> <module.b.src>../../module/module-B/src/main/java</module.b.src> <module.c.src>../../module/module-C/src/main/java</module.c.src> </properties> <build> <plugins><!-- 解决模块相互依赖,综合所有相互依赖代码统一编译 --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <executions> <execution> <id>add-source</id> <phase>generate-sources</phase> <goals> <goal>add-source</goal> </goals> <configuration> <sources> <source>${module.a.src}</source> <source>${module.b.src}</source> <source>${module.c.src}</source> </sources> </configuration> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
【转载地址】http://www.blogjava.net/kuuyee/archive/2011/06/28/353158.html
maven处理循环依赖
在多maven工程的项目里,如果工程间存在循环依赖,构建就会报错。本文介绍一下循环依赖要怎么处理
1、什么是循环依赖
如果工程A依赖工程B,工程B又依赖工程A,就会形成循环依赖。或者A依赖B,B依赖C,C依赖A,也是循环依赖
总的来说,在画出工程依赖图之后,如果发现工程间的依赖连线形成了一个有向循环图,则说明有循环依赖的现象
如果循环依赖发生在工程之间,则会影响构建,因为maven不知道应该先编译哪个工程。如果循环依赖发生在同一个工程的模块之间,虽然不影响编译,但是也是一种不好的实践,说明模块的设计有问题,应该避免
如果在模块内部,有几个类互相调用的话,我觉得可能是正常的。比如观察者模式里面,Observer和Observable就是互相依赖的
2、怎么解决循环依赖
目前知道有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,也可以消除循环依赖
这两种重构方式都是可行的,具体采用哪种方式要根据实际情况来判断。不管采取哪种方式,都需要对代码进行修改,有时候并不是那么容易的
相关推荐
在Java开发中,Maven作为主流的构建工具,管理着项目的依赖关系。然而,当项目引入多个库时,可能会遇到依赖冲突的问题。依赖冲突通常发生在两个或更多库使用相同类的不同版本时,Maven默认会选择最高版本的依赖,但...
在开发java项目的时候,项目编译、测试、运行、打包等等都有着极高的成本,跨部门甚至跨人员之间的项目结构都有可能不一样,除此之外跨部门甚至跨人员之间的项目结构都有可能不一样,这使得成本加倍。maven就是...
使用 jruby 和 bundler 进行混合 java 和 ruby 应用程序开发的插件。 只需在系统中安装java 1.7和maven即可使用。 ##如何使用 将插件依赖添加到你的 pom.xml < groupId>...
分层构建:maven 主架构:spring-boot 服务架构:dubbo、zookeeper 缓存:redission 持久化:mybatis 事务:JTA 令牌管理:JWT 学习收获: 记得住认证、鉴权的意义 记得住...
使用 Munit 测试初始化基于 maven 的简单 Mule 流程 描述 关于使用 Munit 的说明似乎有点稀疏并且有几个。 我从了简单的回声流,并在 pom 中添加了必要的部分,例如:- 添加正确的存储库 说明 MUnit 的正确...
使用API密钥进行身份验证以进行受限操作(例如,下载私有定义)。 自动提供SCM集成以使用对定义所做的更改来更新源代码控制。 支持YAML和JSON格式的定义。 默认情况下连接到SwaggerHub SaaS,并具有可选配置...
因此,我们可以推断Horizon Direct的演示应用可能是一个基于Java的桌面应用,或者是与Java服务器端环境相结合的客户端组件。 【文件名称列表】 "HorizonDemo-master" 这个文件名暗示了这是一个Git仓库的主分支...
项目构建工具:Maven 数据库:Mysql5.7 JDK版本:jdk1.8 Tomcat版本:Tomcat8.x ![emplist](emplist.png) ![empadd](empadd.png) ![deptlist](deptlist.png) ![deptadd](deptadd.png) ![post...
Spring Boot+Layui的高校实验室管理系统,分为两个角色:管理员与普通管理员两个不同权限的角色,管理员有五个菜单,管理员可修改个人信息与密码,登录与退出;首页可通过表看出不同的信息;设备管理:设备...
WxApiServlet是处理请求的实现类,它重新合并微信服务器发来的Post请求封装成MsgRequest对象,然后根据MsgRequest类型的不同(语音,文字,图片)来生成不同类型的处理程序,这里我只做了事件与Text类型的处理...
java笔试题选择题Asciidoctor Maven 插件:示例 该存储库包含一组示例项目,这些项目演示了在 Maven 项目中使用 Asciidoctor Maven 插件的多种方法。 获取示例 ...Maven ...Maven ...Maven ...Asciidoctor Mave
Maven RPM桥 使用maven-rpm-bridge(也称为“ mrb”或“ Br先生”),您可以在不需要设置的... 为了支持影响构造的情况,始终在实例化目标类之前调用任何静态方法(从命令行标志映射)。 使用Callable接口(与Run
简单的Java库,无需使用API KEY就可以使用Google Translate翻译文本 屏幕截图 下载 步骤1.将其添加到存储库末尾的root build.gradle中: allprojects { repositories { ... maven { url ' ...
同时,熟练使用Idea、Maven、Git等开发工具,能有效提升工作效率。 8. **问题定位与协作**:具备良好的问题分析和判断能力,能在复杂情况下快速定位问题,协助研发人员解决问题。此外,良好的沟通协调能力和团队...
后台框架:SpringBoot 前端:Vue 数据库:MySQL Maven 开发环境:JDK、IDEA、Tomcat 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。项目都经过严格调试,确保可以运行! ...
Apache Maven(命令行)创建一个简单的Java项目名称:mvn-cmd :grinning_face_with_smiling_eyes:步骤1:建立Java专案Syntax: mvn archetype:generate -DgroupId=...,Only two things are of concern:1) Grou
mem-Maven环境经理 ... 它通过将~/.m2目录转换为指向当前环境的符号链接来工作,该链接位于~/.m2.<environment> ,例如foobar环境的.m2.foobar 。 系统要求 已知mem可在以下环境中工作: 使用bashLinux发
1. 下载源码以及amqp-client的jar包[https://repo1.maven.org/maven2/com/rabbitmq/amqp-client/3.4.4/amqp-client-3.4.4.jar] 2. 解压源码,将amqp-client-3.4.4.jar放入源码根目录下 3. 修改build.xml...
【标题】:“阶段:工具链的Vagrant文件集” 涉及的主要知识点是Vagrant及其在构建工具链环境中的应用。 Vagrant是一款强大的自动化工具,它允许开发人员在本地创建和管理一致的开发环境。这个“工具链的...
源码获取:博客首页 "资源" 里下载! 功能介绍 springboot酒店宾馆管理系统。该系统为后管系统,无前台。主要分三种角色:管理者/工作人员/前台人员。 主要功能有: 客房:客房标准、房间信息; 订单:入住订单...