如何根据版本过滤掉 Java 方法?

How can I filter out Java methods according to version?

我需要生成三个不同版本的jar 库。 类 的某些方法标有注释,这些注释指定了添加它们时的版本。例如:

public class A {

  @SinceVersion(2)
  public int getTotal() {
    // do something...
  }

  @SinceVersion(5)
  public int getMax() {
    // do something...
  }  

  @SinceVersion(4)
  public int getAverage() {
    // do something...
  }  

}

然后:

这是一个简化的例子。真正的问题跨越 300 类、10 个版本,每个版本有 6 个子版本。

为什么不使用源代码管理(git 等)来管理您的版本?当您使用 v2.0 标记发布时,到那时为止的代码将只有 getTotal()。然后 v4.0 来了一个 long,到那个点的代码会有 getTotal() 和 getAverage() 等等。

每个版本都可以独立管理和构建,并为该特定版本生成特定的 jar 文件。

然后您的客户端将包括它需要的任何版本的 jar。

您可能想研究实现注释处理器。

注释处理器 运行 在编译期间用于创建 and/or 操作代码,我用它们来创建样板代码,以及手动维护起来很乏味的代码,但是结构清晰。

我想 post 我找到的解决方案以防对其他人有帮助。

经过一周的研究,我终于找到了Apache Commons BCEL。该库允许您检查和修改 JVM 中加载的 class;修改后,它可以作为 .class 文件写入文件系统。

像这样的一段代码会生成一个新的 class 文件 没有 一些方法:

import org.apache.bcel.Repository;
import org.apache.bcel.classfile.AnnotationEntry;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ClassGen;

JavaClass clazz = Repository.lookupClass("test.House");
ClassGen cg = new ClassGen(clazz);
Method m = findMethod(clazz, "close");
AnnotationEntry ae = m.getAnnotationEntries(); // process annotations here...
cg.removeMethod(m); // remove the method you want to remove
JavaClass modifiedClazz = cg.getJavaClass();
modifiedClazz.dump("./gen/test/House.class"); // save to a new file

通过遍历 classes 的整棵树(或子包树),可以找到所有受影响的 classes,处理它们的方法,如果注释值符合某些条件则删除它们.