查找 Java Class 的所有传递依赖项,包括仅通过其接口使用的实现 类

Find all transitive dependencies of Java Class including implementation classes used only via their interfaces

我的目标是列出我项目的 public API classes 的所有传递依赖项,并在发生任何代码更改时使用它来集中测试工作对那些依赖项。

例如:

class MyApi {
    MyDao md;
    public void methodA() {
        //do something with md;
    }
}

interface MyDao { }

class MyDaoImpl implements MyDao { }

因此,如果我知道 MyDaoImpl 已被修改(比如从提交历史记录)并且我知道 MyApi.methodA 使用 MyDaoImpl,那么我的测试应该侧重于检查它。我需要 MyApi.methodA() 的依赖项列表,包括 MyDao 和 MyDaoImpl。

到目前为止,我已经尝试了两种工具 - https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jdeps.html and http://depfind.sourceforge.net/ - 它们很有前途,但似乎并没有完全解决问题。对于这两种工具,似乎如果 class 依赖于一个接口,则没有内置方法将该接口的实现作为传递依赖项包含在内。

有没有办法在不进行大量定制的情况下从任何工具中提取此信息?

您可以根据需要使用 JArchitect。 右键单击 UI 中任意位置的方法,然后 select 打开菜单:Select 方法... > ...正在使用我(直接或间接) 导致代码查询,如:

from m in Methods 
let depth0 = m.DepthOfIsUsing("myNamespace.MyClass.MyMethod()")
where depth0  >= 0 orderby depth0
select new { m, depth0 }

问题是此类查询提供了间接用法,但不查找通过接口发生的调用(或在基[=36=中声明的重写方法) ]).

希望可以通过此查询获得您所要求的内容:

// Retrieve the target method by name
let methodTarget = Methods.WithFullName(""myNamespace.MyClass.MyMethod()"").Single()

// Build a ICodeMetric<IMethod,ushort> representing the depth of indirect
// call of the target method.
let indirectCallDepth = 
   methodTarget.ToEnumerable()
   .FillIterative(
       methods => methods.SelectMany(
          m => m.MethodsCallingMe.Union(m.OverriddensBase)))

from m in indirectCallDepth.DefinitionDomain
select new { m, callDepth = indirectCallDepth[m]  }

此查询的两个基石是:

  • 对 FillIterative() 的调用 select 递归间接调用。
  • 对属性IMethod.OverriddensBase的调用,顾名思义。对于方法 M this returns 在基础 class 或接口中声明的所有方法的可枚举,被 M[=29= 覆盖].