为什么 Java 8 和 Java 11 之间解析的依赖项不同?

Mag*_*lex 5 java dependencies maven java-8 java-11

给定一个非常简单的 Maven 项目,其中包含一个包含单个依赖项的 pom 文件:

<?xml version="1.0" encoding="UTF-8"?>
<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">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>maven-test</artifactId>
  <version>1.0-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>org.apache.cxf.xjc-utils</groupId>
      <artifactId>cxf-xjc-runtime</artifactId>
      <version>3.3.0</version>
    </dependency>
  </dependencies>

</project>
Run Code Online (Sandbox Code Playgroud)

运行时mvn dependency:tree根据 Java 版本给出不同的结果。

使用 Java 8:

[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------< org.example:maven-test >-----------------------
[INFO] Building maven-test 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ maven-test ---
[INFO] org.example:maven-test:jar:1.0-SNAPSHOT
[INFO] \- org.apache.cxf.xjc-utils:cxf-xjc-runtime:jar:3.3.0:compile
[INFO]    \- jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.2:compile
[INFO]       \- jakarta.activation:jakarta.activation-api:jar:1.2.1:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.982 s
[INFO] Finished at: 2020-06-22T15:05:56+02:00
[INFO] ------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

使用 Java 11:

[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------< org.example:maven-test >-----------------------
[INFO] Building maven-test 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ maven-test ---
[INFO] org.example:maven-test:jar:1.0-SNAPSHOT
[INFO] \- org.apache.cxf.xjc-utils:cxf-xjc-runtime:jar:3.3.0:compile
[INFO]    +- jakarta.xml.bind:jakarta.xml.bind-api:jar:2.3.2:compile
[INFO]    |  \- jakarta.activation:jakarta.activation-api:jar:1.2.1:compile
[INFO]    +- javax.annotation:javax.annotation-api:jar:1.3.1:compile           <-- This and below only with Java 11
[INFO]    +- javax.xml.ws:jaxws-api:jar:2.3.0:compile
[INFO]    |  +- javax.xml.bind:jaxb-api:jar:2.3.0:compile
[INFO]    |  \- javax.xml.soap:javax.xml.soap-api:jar:1.4.0:compile
[INFO]    \- javax.activation:activation:jar:1.1.1:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.261 s
[INFO] Finished at: 2020-06-22T15:05:51+02:00
[INFO] ------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

我本来希望树在两个 Java 版本下是相同的。

Maven 版本是 3.6.0。

为什么 Java 版本之间解析的依赖项不同?

Mag*_*lex 3

Java版本之间的依赖树不同的原因在于依赖关系:

<dependency>
  <groupId>org.apache.cxf.xjc-utils</groupId>
  <artifactId>cxf-xjc-runtime</artifactId>
  <version>3.3.0</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

这又作为xjc-utils其父级:

<parent>
    <groupId>org.apache.cxf.xjc-utils</groupId>
    <artifactId>xjc-utils</artifactId>
    <version>3.3.0</version>
</parent>
Run Code Online (Sandbox Code Playgroud)

在此 POM 文件中,我们找到使用 Java 8 构建时排除的依赖项:

<profile>
    <id>java9-plus</id>
    <activation>
        <jdk>[9,)</jdk>
    </activation>
    <dependencies>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.ws</groupId>
            <artifactId>jaxws-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
    </dependencies>
 </profile>
Run Code Online (Sandbox Code Playgroud)

这几乎是不言而喻的,只有使用 Java 9 或更高版本时才会包含依赖项,如此范围中所述:<jdk>[9,)</jdk>。该标签的文档指出:

指定当检测到匹配的 JDK 时将激活此配置文件。例如,1.4仅在 JDK 版本 1.4 上激活,而!1.4匹配任何非 1.4 版本的 JDK。

此激活配置文件可确保使用 Java 11 时包含这些依赖项:

[INFO]    +- javax.annotation:javax.annotation-api:jar:1.3.1:compile
[INFO]    +- javax.xml.ws:jaxws-api:jar:2.3.0:compile
[INFO]    |  +- javax.xml.bind:jaxb-api:jar:2.3.0:compile
[INFO]    |  \- javax.xml.soap:javax.xml.soap-api:jar:1.4.0:compile
[INFO]    \- javax.activation:activation:jar:1.1.1:compile
Run Code Online (Sandbox Code Playgroud)

More info about activation can be found in the official Maven documentation:

Activations are the key of a profile. The power of a profile comes from its ability to modify the basic POM only under certain circumstances. Those circumstances are specified via an activation element.

Together with another example of activation based on Java version:

<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
                      https://maven.apache.org/xsd/maven-4.0.0.xsd">
  ...
  <profiles>
    <profile>
      <id>test</id>
      <activation>
        <activeByDefault>false</activeByDefault>
        <jdk>1.5</jdk>
        <os>
          <name>Windows XP</name>
          <family>Windows</family>
          <arch>x86</arch>
          <version>5.1.2600</version>
        </os>
        <property>
          <name>sparrow-type</name>
          <value>African</value>
        </property>
        <file>
          <exists>${basedir}/file2.properties</exists>
          <missing>${basedir}/file1.properties</missing>
        </file>
      </activation>
      ...
    </profile>
  </profiles>
</project>
Run Code Online (Sandbox Code Playgroud)