问题描述
几天以来,我一直在寻找如何在运行时向方法添加注释"的答案,并发现了一个名为 Byte Buddy 的很棒的工具,可以使用它,但仍然无法按我的需要工作到.我确定它必须能够从这个问题中做到这一点 Byte Buddy 能否在运行时创建字段和方法注解?
I've been searching for the answer to "how to add an annotation to the method at runtime" for several days already and found this awesome tool called Byte Buddy, played with it, but still cannot make it work as I need to. I'm sure it must be able to do that from this question Can Byte Buddy create fields and method annotations at runtime?
有这门课:
public class ClassThatNeedsToBeAnnotated {
public void method(int arg1, String arg2) {
// code that we don't want to touch at all, leave it as is
System.out.println("Called method with arguments " + arg1 + " " + arg2);
}
public void method() {
System.out.println("Called method without arguments");
}
}
和这段代码:
public class MainClass {
public static void main(String[] args) {
ByteBuddyAgent.install();
AnnotationDescription description = AnnotationDescription.Builder.ofType(MyClassAnnotation.class)
.define("value", "new")
.build();
new ByteBuddy()
.redefine(ClassThatNeedsToBeAnnotated.class)
.annotateType(description)
.make()
.load(ClassThatNeedsToBeAnnotated.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
}
}
向类添加注释很容易.但是对于方法来说,不改变方法的实现似乎是不可能的.
It is easy to add an annotation to the class.But for the method, it seems to be not possible without changing the method implementation.
Method existingMethod = ClassThatNeedsToBeAnnotated.class.getDeclaredMethods()[0];
AnnotationDescription annotationDescription = AnnotationDescription.Builder.ofType(MyMethodAnnotation.class)
.build();
new ByteBuddy()
.redefine(ClassThatNeedsToBeAnnotated.class)
.annotateType(description)
.method(ElementMatchers.anyOf(existingMethod))
// here I don't want to intercept method, I want to leave the method code untouched. How to do that?
.annotateMethod(annotationDescription)
.make()
.load(ClassThatNeedsToBeAnnotated.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
我确定我只是没有做对,但不幸的是,当方法没有代码更改而只有注释更改时,我找不到示例.
I'm sure that I just don't do it right but unfortunately cannot find an example when there is no code change for the method and only annotation change.
推荐答案
您在 Byte Buddy 中发现了一个我想修复的盲点.Byte Buddy 的早期版本不允许定义注释,但是当它定义时,API 已经被广泛使用,我无法更改它,而且它在实现中也需要一些位.
You found a blindspot in Byte Buddy that I thought of fixing for a while. Early versions of Byte Buddy did not allow for defining annotations but when it did, the API was already so widely used that I could not change it and it would require some bits in the implementation, too.
如果你愿意为添加一个合成方法付出最小的代价,你可以改用类的基数:
If you are willing to pay the minimal price of adding a synthetic method, you can rebase the class instead:
new ByteBuddy().rebase(ClassThatNeedsToBeAnnotated.class)
这样做,您可以只使用当前的 API 并添加 SuperMethodCall
的实现.这将在变基中调用完全相同的方法.
Doing so, you can just use the current API and add an implementation of SuperMethodCall
. This will invoke the very same method in a rebasement.
在此处跟踪 Byte Buddy 的增强功能:https://github.com/raphw/byte-buddy/issues/627
This enhancement of Byte Buddy is tracked here: https://github.com/raphw/byte-buddy/issues/627
更新:在即将发布的 Byte Buddy 1.10.0 中,这可以通过:
UPDATE: In the upcoming Byte Buddy 1.10.0 this is possible by:
new ByteBuddy()
.redefine(ClassThatNeedsToBeAnnotated.class)
.visit(new MemberAttributeExtension.ForMethod()
.annotateMethod(someAnnotation)
.on(matcher))
.make();
注解实例可以通过以下方式获取:AnnotationDescription.Latent.Builder.ofType(AnnotationClass.class).build()
Annotation instance can be get by:AnnotationDescription.Latent.Builder.ofType(AnnotationClass.class).build()
这篇关于使用 Byte Buddy 在运行时添加方法注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!