maven optional dependencies and dependency exclusions

开篇

最近看到mybatis的pom文件里面的dependency都多了一个选项optional.

发现了项目中引入mybatis的依赖,但并没有将mybatis的依赖传递过来。下面以图为证

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.3</version>
    </dependency>

  </dependencies>

下面输出mvn dependency:tree

[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ mvn-excluede-demo ---
[INFO] com.example:mvn-excluede-demo:jar:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.11:test
[INFO] |  \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] \- org.mybatis:mybatis:jar:3.5.3:compile

那我们来看看mybatis中的pom文件是如何写的

只举一部分例子

    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.2</version>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.2.10</version>
      <optional>true</optional>
    </dependency>

可以看到通过<optional>true</optioal>

optional标签

How do optional dependencies work?
Project-A -> Project-B

The diagram above says that Project-A depends on Project-B. When A declares B as an optional dependency in its POM, this relationship remains unchanged. It’s just like a normal build where Project-B will be added in Project-A’s classpath.

Project-X -> Project-A

When another project (Project-X) declares Project-A as a dependency in its POM, the optional nature of the dependency takes effect. Project-B is not included in the classpath of Project-X. You need to declare it directly in the POM of Project X for B to be included in X’s classpath.

上面是官网对于optional的解读,上面的举例就是projectA使用了projectB作为Optional (可选的)依赖,如何A打包作为X的依赖,projectB不会包含在projectX的classpath中。如果需要使用projectB,需要你显式的引用projectB的依赖。

Example

Suppose there is a project named X2 that has similar functionality to Hibernate. It supports many databases such as MySQL, PostgreSQL, and several versions of Oracle. Each supported database requires an additional dependency on a driver jar. All of these dependencies are needed at compile time to build X2. However your project only uses one specific database and doesn’t need drivers for the others. X2 can declare these dependencies as optional, so that when your project declares X2 as a direct dependency in its POM, all the drivers supported by the X2 are not automatically included in your project’s classpath. Your project will have to include an explicit dependency on the specific driver for the one database it does use.

假定如果有一个项目X2和Hibernate类似。它支持多个databases例如mysql,PostgreSQL和多个版本的Oracle.每一个支持的数据库都需要一个额外的依赖在驱动jar包上。在构建x2的时候需要这些。然而你的项目在使用时,你只使用一个特定的数据库而不需要其他的,X2可以申明这些依赖为可选的。你项目在使用时,需要一个明确的依赖来特定的驱动。

exclusion

如何依赖是如下形式的

Project-A
   -> Project-B
        -> Project-D <! -- This dependency should be excluded -->
              -> Project-E
              -> Project-F
   -> Project C

如果projectA 依赖于ProjectB和ProjectC,projectB是依赖于E和F

所以ProjectA会依赖B、C、D、E、F

如果你想要ProjectD将其加入到ProjectA的classPath中。项目B的开发者可以标致ProjectD的optional为true。

手动排除当前层级的

但是很不幸的,他们并没有,所以你需要在ProjectA的pom文件中,手动去排除

<dependencies>
    <dependency>
      <groupId>sample.ProjectB</groupId>
      <artifactId>Project-B</artifactId>
      <version>1.0-SNAPSHOT</version>
      <exclusions>
        <exclusion>
          <groupId>sample.ProjectD</groupId> <!-- Exclude Project-D from Project-B -->
          <artifactId>Project-D</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>
依赖中的排除那一个层级消失,不会传递给下一个依赖

如果有一个项目X依赖于ProjectA,那么ProjectD是否会被exclude

答案是正确的。会被exclude

依赖并不是全局的,有点局部变量的味道

如果项目X同时又依赖于ProjectY,projectY里面依赖于ProjectD,这是ProjectD并不会被全局的exclude,他是projectY的合法依赖。

下面,我们来看看

英文原文

If you deploy Project-A to a repository, and Project-X declares a normal dependency on Project-A, will Project-D still be excluded from the classpath?

Project-X -> Project-A
The answer is Yes. Project-A has declared that it doesn't need Project-D to run, so it won't be brought in as a transitive dependency of Project-A.

Now, consider that Project-X depends on Project-Y, as in the diagram below:

Project-X -> Project-Y
               -> Project-B
                    -> Project-D
                       ...
Project-Y also has a dependency on Project-B, and it does need the features supported by Project-D. Therefore, it will NOT place an exclusion on Project-D in its dependency list. It may also supply an additional repository, from which it can resolve Project-E. In this case, it's important that Project-D is not excluded globally, since it is a legitimate dependency of Project-Y.
排除跨层级的

如果想要在ProjectB中排除E

<dependency>
      <groupId>sample.ProjectB</groupId>
      <artifactId>Project-B</artifactId>
      <version>1.0-SNAPSHOT</version>
      <exclusions>
        <exclusion>
          <groupId>sample.ProjectE</groupId> <!-- Exclude Project-E from Project-B -->
          <artifactId>Project-E</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

参考资料:

  • https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html
  • https://cloud.tencent.com/developer/article/1028070
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值