查看dependencyManagement的依赖树

View dependency tree of dependencyManagement

我们都知道依赖树对于解决传递依赖冲突至关重要。 dependencyManagement 也是如此,但我找不到以与 dependencies 类似的方式为其打印依赖关系树的方法。

是否有插件或其他东西可以提供帮助?

Maven 版本:3.2.3

编辑

对于认为此问题与另一个问题重复的人,请考虑:

  1. 另一个问题是关于依赖管理的插件管理。

  2. 另一个问题没有提到生成依赖树。

我找不到任何打印依赖管理部分的依赖树的插件。

但是,您可以为此编写自己的 MOJO。以下所有代码都是使用 Maven 3.3.9 编写和测试的,通过修改新 MOJO 的依赖项可以很容易地使其适应您当前的 Maven 版本。

Maven插件的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">
    <modelVersion>4.0.0</modelVersion>
    <groupId>sample.plugin</groupId>
    <artifactId>test-maven-plugin</artifactId>
    <version>1.0.0</version>
    <packaging>maven-plugin</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>3.3.9</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>3.4</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-core</artifactId>
            <version>3.3.9</version>
        </dependency>
    </dependencies>
</project>

MOJO 本身将是:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.DefaultProjectBuildingRequest;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingRequest;
import org.eclipse.aether.transfer.ArtifactNotFoundException;

@Mojo(name = "foo", requiresDependencyResolution = ResolutionScope.TEST)
public class MyMojo extends AbstractMojo {

    @Parameter(defaultValue = "${project}", readonly = true, required = true)
    private MavenProject project;

    @Parameter(defaultValue = "${session}", readonly = true, required = true)
    private MavenSession session;

    @Component
    private ArtifactHandler artifactHandler;

    @Component
    private ProjectBuilder projectBuilder;

    public void execute() throws MojoExecutionException, MojoFailureException {
        Set<Artifact> visitedArtifacts = new HashSet<Artifact>();
        for (Dependency dependency : project.getDependencyManagement().getDependencies()) {
            printDependencyTree(toArtifact(dependency), "", visitedArtifacts);
        }
    }

    private void printDependencyTree(Artifact artifact, String level, Set<Artifact> visitedArtifacts) throws MojoExecutionException {
        getLog().info(level + "+ " + artifact);
        for (Dependency transitive : getTransitiveDependencies(artifact)) {
            Artifact transitiveArtifact = toArtifact(transitive);
            if (!visitedArtifacts.contains(transitiveArtifact)) {
                visitedArtifacts.add(transitiveArtifact);
                printDependencyTree(transitiveArtifact, level + "  ", visitedArtifacts);
            }
        }
    }

    private List<Dependency> getTransitiveDependencies(Artifact artifact) throws MojoExecutionException {
        try {
            ProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest(session.getProjectBuildingRequest());
            buildingRequest.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_MINIMAL);
            buildingRequest.setProject(null);
            MavenProject mavenProject = projectBuilder.build(artifact, buildingRequest).getProject();
            return mavenProject.getDependencies();
        } catch (ProjectBuildingException e) {
            if (e.getCause() != null && e.getCause().getCause() instanceof ArtifactNotFoundException) {
                //ignore
                return new ArrayList<Dependency>();
            }
            throw new MojoExecutionException("Error while building project", e);
        }
    }

    private Artifact toArtifact(Dependency dependency) {
        return new DefaultArtifact(dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), dependency.getScope(), dependency.getType(), dependency.getClassifier(), artifactHandler);
    }

}

这有点复杂,但主要成分是:

  • 我们注入了当前的Maven项目,为此我们在依赖管理部分用project.getDependencyManagement().getDependencies()解决了依赖关系。
  • 对于每个依赖项,我们通过使用 ProjectBuilder API 在内存中构建 Maven 项目来解决其传递依赖项。这需要将我们的Dependency转化为Artifact(这是在toArtifact的帮助下完成的),构建一个ProjectBuildingRequest设置项目为null(我注意到我们还需要将验证级别设置为最小,这样 API 就不会在稍微不一致的 POM 上失败),最后调用 projectBuilder.build 来构建项目。有了这个项目,我们就可以 return 它与 mavenProject.getDependencies().
  • 的依赖关系
  • 所有这些都是在一个递归方法中完成的,该方法将简单地打印工件的基本信息。递归级别是通过在每次向下一级时添加两个空格来实现的。
  • 此外,由于我们可能会重新访问已经遇到的工件(因此会陷入无限循环),所以我保留了一组访问过的工件,并在再次遇到已经遇到的工件时结束树。
  • 忽略 ArtifactNotFoundException 异常,如果我们尝试下载不知何故未找到的工件,则可能会发生这种情况。
  • 第一次启动时,项目构建器 API 将从您配置的存储库下载所有依赖项,因此会使日志混乱。您将需要再次启动它以更好地查看输出。

作为示例,我使用以下依赖管理部分对此进行了测试

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-annotations</artifactId>
            <version>3.4.0.GA</version>
        </dependency>
    </dependencies>
</dependencyManagement>

结果是:

+ org.hibernate:hibernate-annotations:jar:3.4.0.GA
  + org.hibernate:ejb3-persistence:jar:1.0.2.GA:compile
  + org.hibernate:hibernate-commons-annotations:jar:3.1.0.GA:compile
    + org.slf4j:slf4j-api:jar:1.4.2:compile
      + junit:junit:jar:3.8.1:test
  + org.hibernate:hibernate-core:jar:3.3.0.SP1:compile
    + antlr:antlr:jar:2.7.6:compile
    + commons-collections:commons-collections:jar:3.1:compile
    + dom4j:dom4j:jar:1.6.1:compile
      + jaxme:jaxme-api:jar:0.3:compile
      + jaxen:jaxen:jar:1.1-beta-6:compile
        + dom4j:dom4j:jar:1.5.2:compile
          + jaxen:jaxen:jar:1.1-beta-4:compile
            + jdom:jdom:jar:b10:compile
            + xerces:xmlParserAPIs:jar:2.6.2:compile
            + xerces:xercesImpl:jar:2.6.2:compile
            + xom:xom:jar:1.0b3:compile
              + xerces:xmlParserAPIs:jar:2.6.1:compile
              + xerces:xercesImpl:jar:2.2.1:compile
              + com.ibm.icu:icu4j:jar:2.6.1:compile
              + xalan:xalan:jar:2.6.0:compile
                + xml-apis:xml-apis:jar:2.0.2:compile
                + xerces:xercesImpl:jar:2.6.0:compile
              + org.ccil.cowan.tagsoup:tagsoup:jar:0.9.7:compile
              + javax.servlet:servlet-api:jar:2.4:provided
          + msv:xsdlib:jar:20030807:compile
          + msv:relaxngDatatype:jar:20030807:compile
          + pull-parser:pull-parser:jar:2:compile
          + xpp3:xpp3:jar:1.1.3.3:compile
          + stax:stax-api:jar:1.0:compile
          + junitperf:junitperf:jar:1.8:test
          + stax:stax-ri:jar:1.0:test
          + xalan:xalan:jar:2.5.1:test
        + jdom:jdom:jar:1.0:compile
          + xml-apis:xml-apis:jar:1.0.b2:compile
          + jaxen:jaxen:jar:1.0-FCS:compile
          + saxpath:saxpath:jar:1.0-FCS:compile
          + xalan:xalan:jar:2.5.0:compile
    + javax.transaction:jta:jar:1.1:compile
    + javax.security:jaas:jar:1.0.01:provided
    + javax.security:jacc:jar:1.0:provided
    + ant:ant:jar:1.6.5:provided
      + xml-apis:xml-apis:jar:1.3.04:compile
    + javassist:javassist:jar:3.4.GA:compile
    + org.hibernate:hibernate-cglib-repack:jar:2.1_3:compile

要对此进行测试,您当然需要将该 MOJO 绑定到测试 Maven 项目,并且您需要事先安装 MOJO。

  1. 运行 mvn clean install 在具有上述 POM 的 Maven 插件上
  2. 创建一个声明该插件的新测试 Maven 项目。

上面MOJO的插件配置可以是:

<plugin>
    <groupId>sample.plugin</groupId>
    <artifactId>test-maven-plugin</artifactId>
    <version>1.0.0</version>
    <executions>
        <execution>
            <id>t</id>
            <goals>
                <goal>foo</goal>
            </goals>
            <phase><!-- something --></phase>
        </execution>
    </executions>
</plugin>