博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于maven可选依赖和排除依赖的学习
阅读量:3580 次
发布时间:2019-05-20

本文共 3816 字,大约阅读时间需要 12 分钟。

原文地址:

      

      了解可选依赖和排除依赖的功能,能够帮助我们更好的理解依赖是什么、怎样使用、如何工作和何时最适宜应用。其中,排除依赖是作为依赖的基本概念而不是处于pom层。

一、    可选依赖

       当一个项目不适合分割成多个子模块的时候,我们可以使用可选依赖。它的思想在于某些依赖只应用于某些功能,而且当没有该功能时也不存在该依赖。理想状况下,一个功能可能被划分为一个子模块,该子模块是一个只有核心功能的项目,由于当你要使用这个子工程的功能的时候,你会需要它的全部,所以这个子工程只含有非可选性依赖。

      然而,如果工程不可被分割,这些依赖被声明为可选。如果一个用户想要使用和可选性依赖相关的功能,他们必须要在工程中重新声明可选性依赖。也许可选依赖和排除依赖不是解决问题的最好方法,但是不失为一种有效的解决方案。

      1. 为何使用可选依赖

      声明可选依赖不仅对于节省空间/内存等是重要的,而且对于使用一个工程的时候控制实际依赖的列表也是非常重要的。因为jar包最终可能编译成WAR、EAR、EJB等等,包含错误的jar包可能产生违反许可证协议、导致类路径错误等问题。

      2.如何使用optional标记

      在你的依赖声明中简单地将<optional>标记设置成true,就能将一个依赖声明为可选的。示例如下

  ...
  
    
    
      
sample.ProjectA
      
Project-A
      
1.0
      
compile
      
true
    
  
 

      3.可选依赖是如何工作的?

Project-A -> Project-B

      如上图所以projectA依赖projectB,当A在它的pom中声明B作为它的可选依赖时,这个关系会一直保持。 这就像在通常的构建中,projectB会被加到它的类路径中。

Project-X -> Project-A

      但是当另外一个工程projectX在它的pom中声明A作为其依赖时,可选性依赖这时就发挥作用了。你会发现projectB并不存在projectX的类路径中。如果X的类路径要包含B那么需要在你的pom中直接进行声明。

      4.例子:

      让我们假设现在有这样一个和Hibernate有类似功能的工程X2,支持多种诸如mysql, postgre, oracle等数据库驱动/依赖,所有这些驱动/依赖是X2但不是你的工程所需要的,所以一种比较可行的方法就是X2将这些驱动/依赖声明为可选的。这样,无论任何时候当你的工程在pom中声明X2作为直接依赖,X2所支持的这些驱动/依赖都不会被自动加到你工程的类路径中,相反地,你必须要直接声明需要使用的数据库驱动/依赖。

二、  排除依赖

       由于maven2.x会传递解析依赖,所以很有可能一些你不需要的依赖也会包含在工程类路径中。例如,一些你依赖的工程可能没有正确的声明它们的依赖集。为了解决这种特殊情况,maven2.x已经引入了显式排除依赖的概念。排除是设置在pom中指定的依赖上,并且有指定的groupId和artifactId来标注。当你构建工程时,该物件不会像解析加载依赖一样被加载到你工程的类路径中。

       1. 如何使用排除依赖

       我们在pom中的<dependency>段下面加上<exclusions>标签。

  ...
  
    
      
sample.ProjectA
      
Project-A
      
1.0
      
compile
      
        
 
          
sample.ProjectB
          
Project-B
        
      
    
  
 

       2.排除依赖是如何工作的并且在何时使用它(作为最后一种解决方法)

Project-A
   -> Project-B
        -> Project-D 
              -> Project-E
              -> Project-F
   -> Project C

       如上图所示,Project-A依赖Project-B和C,Project-B依赖Project-D,Project-D依赖Project-E和F,默认的Project-A的类路径会包含:

B, C, D, E, F

       如果由于我们知道Project-D的某些依赖在仓库中丢失,那么我们不想Project-D和它所有的依赖加载到Project-A的类路径中,而且也不想/不需要依赖Project-D的Project-B的功能。在这种情况下,Project-B的开发者会提供一个Project-D的 <optional>true</optional>依赖,如下:

  
sample.ProjectD
  
ProjectD
  
1.0-SNAPSHOT
  
true

</dependency>

      然而,并不能达到你想要的效果。作为最后一种解决方法你仍然可以选择将它在Project-A中排除掉。如下:

  
4.0.0
  
sample.ProjectA
  
Project-A
  
1.0-SNAPSHOT
  
jar
  ...
  
    
      
sample.ProjectB
      
Project-B
      
1.0-SNAPSHOT
      
        
          
sample.ProjectD
          
Project-D
        
      
    
  
 

      如果我们将Project-A部署到一个仓库中,而且Project-X声明了一个普通依赖到Project-A。那么Project-D是不是依旧从类路径中排除了?

Project-X -> Project-A

       答案是yes。Project-A已经声明了它不需要Project-D,所以它不会作为Project-A的传递依赖而引入。那么考虑下图的Project-X依赖Project-Y,

Project-X -> Project-Y
               -> Project-B
                    -> Project-D
                       ...

       Project-Y依赖于Project-B,并且它有需要Project-D所支持的功能,所以不能在Project-D的依赖列表中声明排除。也可再提供一个额外的我们可以解析Project-E的仓库。在这种情况下,不能将Project-D全局排除,因为它是Project-Y的合法依赖。

      在另外一种场景中,如果我们不需要的依赖是Project-E而不是Project-D,我们如何排除它呢?如下图:

Project-A
   -> Project-B
        -> Project-D
              -> Project-E 
              -> Project-F
   -> Project C

      排除会影响到在依赖图上所有它的声明点以后的部分。如果你想排除Project-E而不是Project-D,可以简单的将排除指向Project-E。但是你无法将排除作用到Project-D,因为你无法改变Project-D的pom,如果你想这样,你应该用选择依赖而不是排除,或者将Project-D分成多个子工程,每个只有普通依赖。

  
4.0.0
  
sample.ProjectA
  
Project-A
  
1.0-SNAPSHOT
  
jar
  ...
  
    
      
sample.ProjectB
      
Project-B
      
1.0-SNAPSHOT
      
        
          
sample.ProjectE
          
Project-E
        
      
    
  

      3.为什么排除是依赖的基本概念,而不是在pom层上?

       这主要是为了确保依赖图是可预测的,并且防止排除不该排除的依赖。如果你用到了这个最终的解决方法并且必须要把它放到排除中,你必须绝对清楚你讨厌的传递依赖中有哪些依赖会被引入。

 

转载地址:http://xwcgj.baihongyu.com/

你可能感兴趣的文章
Java基础入门 StringBuffer类
查看>>
Java基础入门 currentTimeMillis方法
查看>>
Java基础入门 arraycopy方法
查看>>
Java基础入门 Math类
查看>>
Java基础入门 Random类
查看>>
Java基础入门 Date类
查看>>
Java基础入门 Calendar类
查看>>
Java基础入门 DateFormat类
查看>>
Java基础入门 Window类及Panel类
查看>>
Java基础入门 AWT事件处理
查看>>
Java基础入门 鼠标事件
查看>>
Java基础入门 键盘事件
查看>>
Java基础入门 GridLayout
查看>>
JavaEE Bean的两种常用作用域 singleton(单例)和prototype(原型)
查看>>
MySQL 数据库索引
查看>>
JavaEE Spring与MyBatis的整合之传统DAO方式整合(教材学习笔记)
查看>>
JavaEE MyBatis与Spring的整合——基于mapper接口方式开发(教材学习笔记)
查看>>
Omap138开发板下以uboot2012.04.01为例分析uboot执行(五)
查看>>
Omap138开发板下以uboot2012.04.01为例分析uboot执行(六)
查看>>
Omap138开发板下以uboot2012.04.01为例分析uboot执行(七)
查看>>