本文主要介绍如何优化pom,杜绝重复(DRY)。

1)模块重复依赖;

2)坐标版本号重复;

3)兄弟依赖

一、项目骨架

上图说明:

  1. multi-module-project是一个有多个模块构成的项目,模块分别为:web-service、web-app、web-dal
  2. web-service、web-app、web-dal分别依赖与log4j
  3. web-app同时依赖web-service和web-dal,因为这三个模块属于同一个project,所以这种依赖叫做兄弟依赖。

 二、模块重复依赖

2.1 问题

由于三个模块同时依赖与log4j组件,如果在web-service,web-app,以及web-dal的pom文件中分别都加入对log4j的依赖(首先,这是可以的)就会出现一个问题:当log4j有新的版本出现,且自己的项目想引入这个新版本,由于每个模块都配置了对log4j的依赖,那么就需要在每个模块的pom文件中进行修改,工作量很大,且如果模块多,类似的重复依赖也多,就容易出现有些模块漏修改的问题,容易产生问题。

该问题就犹如有很多重复代码大量存在于不同的模块,当有针对这块重复代码逻辑修改的时候,就需要大量的人力去到处修改,且容易出错。怎么办?代码中的问题可以通过把这个重复代码单独封装,然后多出进行调用。这样有需求变动时只需要修改一个地方即可。

2.2 解决方案

maven的pom文件优化类似,maven中可以将这些子模块中相同的依赖移到父模块的dependencyManagement节点。

最佳实践:如果有两个以上的子模块共同依赖一个组件,那么对于这个组建的依赖就应该放在父模块的dependencyManagement节点

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>>4.0.0</modelVersion>
  6.  
  7. <groupId>com.cnblogs.kmpp</groupId>
  8. <artifactId>multi-module</artifactId>
  9. <packaging>pom</packaging>
  10. <version>1.0-SNAPSHOT</version>
  11. <modules>
  12. <module>web-app</module>
  13. <module>web-service</module>
  14. <module>web-dal</module>
  15. </modules>
  16. <dependencyManagement>
  17. <dependencies>
  18. <dependency>
  19. <groupId>junit</groupId>
  20. <artifactId>junit</artifactId>
  21. <version>4.12</version>
  22. </dependency>
  23. </dependencies>
  24. </dependencyManagement>
  25. </project>

当然如果将依赖移到父模块的dependencyManagement模块后,需要在子模块中将对应的依赖删除,否则,子模块的配置会覆盖父模块的配置。

三、版本号重复

3.1 问题演示

  1. <dependencies>
  2. <dependency>
  3. <groupId>junit</groupId>
  4. <artifactId>junit</artifactId>
  5. <version>4.12</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.hibernate</groupId>
  9. <artifactId>hibernate-annotations</artifactId>
  10. <version>3.3.0.ga</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.hibernate</groupId>
  14. <artifactId>hibernate-commons-annotations</artifactId>
  15. <version>3.3.0.ga</version>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.hibernate</groupId>
  19. <artifactId>hibernate</artifactId>
  20. <version>3.2.5.ga</version>
  21. </dependency>
  22. </dependencies>

上面的pom配置中作为org.hibernate下面的组件,版本号重复了,一般来说,一个组织(groupid)下面的组件的版本号是一致的,且一起更新,和上面说的多个模块重复依赖一个组件类型,当同一个版本号多处出现时,如果修改,就会出现工作量大且有漏修改的风险。

3.2 解决

使用属性元素(property),统一定义版本号,多处进行使用:

  1. <properties>
  2. <hibernate.annotations.version>3.3.0.ga</hibernate.annotations.version>
  3. </properties>
  4. <dependencyManagement>
  5. <dependencies>
  6. <dependency>
  7. <groupId>junit</groupId>
  8. <artifactId>junit</artifactId>
  9. <version>4.12</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.hibernate</groupId>
  13. <artifactId>hibernate-annotations</artifactId>
  14. <version>${hibernate.annotations.version}</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.hibernate</groupId>
  18. <artifactId>hibernate-commons-annotations</artifactId>
  19. <version>${hibernate.annotations.version}</version>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.hibernate</groupId>
  23. <artifactId>hibernate</artifactId>
  24. <version>${hibernate.annotations.version}</version>
  25. </dependency>
  26. </dependencies>
  27. </dependencyManagement>

这样当org.hibernate的版本号变化的时候只需要修改以地方。其实版本号类似于程序里面的magic number。不管是不是多次使用,最好都通过定义property来实现,上面的junit的版本号也应该预先在property中进行定义,然后再使用。

四、兄弟依赖

4.1 问题

web-app依赖web-dal和web-service组件

  1. <dependency>
  2. <groupId>com.cnblogs.kmpp</groupId>
  3. <artifactId>web-service</artifactId>
  4. <version>1.0-SNAPSHOT</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.cnblogs.kmpp</groupId>
  8. <artifactId>web-dal</artifactId>
  9. <version>1.0-SNAPSHOT</version>
  10. </dependency>

上面的依赖同样有重复:groupId和version。

4.2 解决

因为web-app、web-dal以及web-service作为兄弟模块他们的groupId和version是和父模块是一样的。所以兄弟依赖的groupId和version可以使用父模块的数据:

  1. <dependency>
  2. <groupId>${parent.groupId}</groupId>
  3. <artifactId>web-service</artifactId>
  4. <version>${parent.version}</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>${parent.groupId}</groupId>
  8. <artifactId>web-dal</artifactId>
  9. <version>${parent.version}</version>
  10. </dependency>

当然,兄弟依赖的重复也可以通过property来定义解决,但是没有直接使用父模块属性方便。

五、maven 依赖分析

maven已经提供了命令:

  1. mvn dependency:analyze,使用该命令就可以看到maven分析的结果和建议
  2. mvn dependency:tree,使用该命令可以看到maven的依赖树。

六、结束语

DRY works everywhere and always will do.

Maven(5)-优化和重构POM的更多相关文章

  1. Maven学习-优化和重构POM

    在一个复杂的项目中,项目的各个模块存在各种相互依赖关系.优化一个多模块项目的POM最好通过几步来做.总的来说,我们总是寻找一个POM中的重复或者多个兄弟POM中的重复.在多模块项目中依赖重复的模式主要 ...

  2. 学习笔记——Maven实战(二)POM重构之增还是删

    重构是广大开发者再熟悉不过的技术,在Martin Fowler的<重构——改善既有代码的设计>一书中,其定义为“重构(名词):对软件内部结构的一种调整,目的是在不改变软件之可察行为前提下, ...

  3. maven实战(04)_在pom中使用properties

    使用常量不仅让代码变得简洁,更重要的是可以避免重复,在需要更改的时候,只需要修改一处,降低了错误发生的概率. <project> <modelVersion>4.0.0< ...

  4. 根据自己的需要,把别人开发好的东西搬过来,优化and重构,在优化的过程中,甚至也会弄出一套全新的东西(转)

    赵海平在今年三月份来到阿里,听毕玄(他现任主管)说去年五六月份就跟赵海平聊上了.有人问:为啥 BAT 三大巨头,你看中了阿里巴巴?在今天现场达一千多人的分享中赵海平给出了回复:“因为百度和腾讯没找我呗 ...

  5. 【原】使用IDEA创建Maven工程时提示"...xxx/pom.xml already exists in VFS"的解决

    问题:使用IDEA创建Maven工程时提示"...xxx/pom.xml already exists in VFS",怎么办? 解决:如果只是删除工程,还会有这样的提示.说到底, ...

  6. Eclipse搭建maven project web war项目pom.xml报错

    在eclipse中搭建maven project时,在不使用模板的情况下,搭建的web项目会报错. 操作步骤如下: 1.勾选Create a simple project ,因为如果不勾选系统会提供模 ...

  7. Maven内置属性,pom属性

    内置属性(Maven预定义,用户可以直接使用) ${basedir}表示项目根目录,即包含pom.xml文件的目录; ${version}表示项目版本; ${project.basedir}同${ba ...

  8. maven的三种工程pom、jar、war的区别

    转: maven的三种工程pom.jar.war的区别 2018年09月03日 10:02:53 houjx3 阅读数:2918更多 个人分类: maven   1.pom工程:用在父级工程或聚合工程 ...

  9. maven 配置多模块项目 pom modules

    所有用Maven管理的真实的项目都应该是分模块的,每个模块都对应着一个pom.xml.它们之间通过继承和聚合(也称作多模块,multi-module)相互关联.那么,为什么要这么做呢?我们明明在开发一 ...

随机推荐

  1. 【BZOJ4154】[Ipsc2015]Generating Synergy KDtree

    [BZOJ4154][Ipsc2015]Generating Synergy Description 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问 ...

  2. PLSQL使用技巧----加快你的编程效率

    使用PLSQL 编程效率明显有所提高了 1.登录后默认自动选中My Objects      默认情况下,PLSQL Developer登录后,Brower里会选择All objects,如果你登录的 ...

  3. iOS设备获取总结

    1.获取iOS设备的各种信息 // 这个方法后面会列出来 NSString *deviceName = [self getDeviceName]; NSLog(@"设备型号-->%@& ...

  4. Android开发之深入理解泛型extends和super的区别

    摘要: 什么是泛型?什么是擦除边界?什么是上界限定或下界限定(子类型限定或超类型限定)?什么是类型安全?泛型extends关和super关键字结合通配符?使用的区别,两种泛型在实际Android开发中 ...

  5. SpringBoot_集成Shiro后获取当前用户

    //SecurityUtils.getSubject().getPrincipal();  就可以获取了 protected User getCurrentUser(){ return (User) ...

  6. mysql练习(待补充)

    2.查询‘生物’课程比‘物理’课程成绩高的所有学生的学号 思路: 获取所有生物课程的人(学号,成绩)-临时表 获取所有物理课程的人(学号,成绩)-临时表 根据学号连接两个临时表: 学号 生物成绩 物理 ...

  7. Android:日常学习笔记(10)———使用LitePal操作数据库

    Android:日常学习笔记(10)———使用LitePal操作数据库 引入LitePal 什么是LitePal LitePal是一款开源的Android数据库框架,采用了对象关系映射(ORM)的模式 ...

  8. 3.26课·········window.document对象

    1.Window.document对象 一.找到元素:    docunment.getElementById("id"):根据id找,最多找一个:    var a =docun ...

  9. hadoop自带例子SecondarySort源码分析MapReduce原理

    这里分析MapReduce原理并没用WordCount,目前没用过hadoop也没接触过大数据,感觉,只是感觉,在项目中,如果真的用到了MapReduce那待排序的肯定会更加实用. 先贴上源码 pac ...

  10. AJAX请求时status返回状态明细表

    AJAX请求时status返回状态明细表 readyState的五种状态2010-03-04 18:24对于readyState的五种状态的描述或者说定义,很多Ajax书(英文原版)中大都语焉不详 在 ...