Java 使用bytebuddy是否可以增强注释具有特定属性值的字段?
我试图使用bytebuddy来重新定义现有的类。我正在寻找用特定注释注释的字段。我已经用这样的代码弄明白了:Java 使用bytebuddy是否可以增强注释具有特定属性值的字段?,java,byte-buddy,Java,Byte Buddy,我试图使用bytebuddy来重新定义现有的类。我正在寻找用特定注释注释的字段。我已经用这样的代码弄明白了: new ByteBuddy() .redefine(<some class>) .field( ElementMatchers.isAnnotatedWith(<some annotation>) ) ... new ByteBuddy() .redefine
new ByteBuddy()
.redefine(<some class>)
.field(
ElementMatchers.isAnnotatedWith(<some annotation>)
)
...
new ByteBuddy()
.redefine(<some class>)
.field(
ElementMatchers.isAnnotatedWith(<some annotation>)
.havingAttribute(<some attribute>, "value")
)
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void onMethodEnter(@AnnotationValueExtractor(annotationClassName = "co.elastic.apm.api.CaptureSpan", method = "value") String spanName) {
if (spanName.equals("foo")) {
// do something special
}
}
public class NeedsLazyToOneNoProxy<T extends AnnotationSource> extends ElementMatcher.Junction.AbstractBase<T> {
public boolean matches(T target) {
AnnotationDescription oneToOneAnnotation = target.getDeclaredAnnotations().ofType(OneToOne.class);
try {
if (oneToOneAnnotation != null) {
OneToOne oneToOne = (OneToOne) ((AnnotationDescription.Loadable) oneToOneAnnotation).load();
FetchType fetchType = oneToOne.fetch();
return fetchType == FetchType.LAZY;
}
return false;
}
catch (ClassNotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
newbytebuddy()
.重新定义()
.场(
ElementMatchers.isAnnotatedWith()
)
...
我想做的是进一步细化我的ElementMatcher,以便在指定的注释中包含一个属性检查-类似这样:
new ByteBuddy()
.redefine(<some class>)
.field(
ElementMatchers.isAnnotatedWith(<some annotation>)
)
...
new ByteBuddy()
.redefine(<some class>)
.field(
ElementMatchers.isAnnotatedWith(<some annotation>)
.havingAttribute(<some attribute>, "value")
)
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void onMethodEnter(@AnnotationValueExtractor(annotationClassName = "co.elastic.apm.api.CaptureSpan", method = "value") String spanName) {
if (spanName.equals("foo")) {
// do something special
}
}
public class NeedsLazyToOneNoProxy<T extends AnnotationSource> extends ElementMatcher.Junction.AbstractBase<T> {
public boolean matches(T target) {
AnnotationDescription oneToOneAnnotation = target.getDeclaredAnnotations().ofType(OneToOne.class);
try {
if (oneToOneAnnotation != null) {
OneToOne oneToOne = (OneToOne) ((AnnotationDescription.Loadable) oneToOneAnnotation).load();
FetchType fetchType = oneToOne.fetch();
return fetchType == FetchType.LAZY;
}
return false;
}
catch (ClassNotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
newbytebuddy()
.重新定义()
.场(
ElementMatchers.isAnnotatedWith()
.具有属性(,“值”)
)
我要找的是做“有属性”部分的方法。这是可能的还是我走错了路?任何见解都值得赞赏。一种方法是创建一个
Advice.OffsetMapping.Factory
,它允许您在建议中注入注释值,如下所示:
new ByteBuddy()
.redefine(<some class>)
.field(
ElementMatchers.isAnnotatedWith(<some annotation>)
)
...
new ByteBuddy()
.redefine(<some class>)
.field(
ElementMatchers.isAnnotatedWith(<some annotation>)
.havingAttribute(<some attribute>, "value")
)
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void onMethodEnter(@AnnotationValueExtractor(annotationClassName = "co.elastic.apm.api.CaptureSpan", method = "value") String spanName) {
if (spanName.equals("foo")) {
// do something special
}
}
public class NeedsLazyToOneNoProxy<T extends AnnotationSource> extends ElementMatcher.Junction.AbstractBase<T> {
public boolean matches(T target) {
AnnotationDescription oneToOneAnnotation = target.getDeclaredAnnotations().ofType(OneToOne.class);
try {
if (oneToOneAnnotation != null) {
OneToOne oneToOne = (OneToOne) ((AnnotationDescription.Loadable) oneToOneAnnotation).load();
FetchType fetchType = oneToOne.fetch();
return fetchType == FetchType.LAZY;
}
return false;
}
catch (ClassNotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
另见:
我最终实现了一个自定义ElementMatcher,如下所示:
new ByteBuddy()
.redefine(<some class>)
.field(
ElementMatchers.isAnnotatedWith(<some annotation>)
)
...
new ByteBuddy()
.redefine(<some class>)
.field(
ElementMatchers.isAnnotatedWith(<some annotation>)
.havingAttribute(<some attribute>, "value")
)
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void onMethodEnter(@AnnotationValueExtractor(annotationClassName = "co.elastic.apm.api.CaptureSpan", method = "value") String spanName) {
if (spanName.equals("foo")) {
// do something special
}
}
public class NeedsLazyToOneNoProxy<T extends AnnotationSource> extends ElementMatcher.Junction.AbstractBase<T> {
public boolean matches(T target) {
AnnotationDescription oneToOneAnnotation = target.getDeclaredAnnotations().ofType(OneToOne.class);
try {
if (oneToOneAnnotation != null) {
OneToOne oneToOne = (OneToOne) ((AnnotationDescription.Loadable) oneToOneAnnotation).load();
FetchType fetchType = oneToOne.fetch();
return fetchType == FetchType.LAZY;
}
return false;
}
catch (ClassNotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
公共类NeedsAzytoonenoproxy扩展了ElementMatcher.Junction.AbstractBase{
公共布尔匹配(T目标){
AnnotationDescription oneToOneAnnotation=target.getDeclaredAnnotations(),类型为(OneToOne.class);
试一试{
if(onetooneanotation!=null){
OneToOne OneToOne=(OneToOne)((AnnotationDescription.Loadable)onetooneanotation.load();
FetchType FetchType=oneToOne.fetch();
返回fetchType==fetchType.LAZY;
}
返回false;
}
catch(classnotfounde异常){
抛出新的RuntimeException(e.getMessage(),e);
}
}
}
我使用此元素匹配器来确定是否应该向现有的@OneToOne关系添加@LazyToOne注释。我是ByteBuddy的初学者,在@Advice注释方面没有跟上速度。我不知道我怎样才能用它来解决我的特殊问题。相反,我最终要做的是实现一个自定义ElementMatcher,它查找我感兴趣的特定注释,加载此注释,然后检查加载的注释上的属性值。不确定这是否是推荐的方法,但它起了作用。加载注释通常很好。我会避免在您的解决方案中使用强制转换,您可以使用Byte Buddy的API实现这一点。如果基础注释已经来自加载的类型,则基本上只需使用hoods下的反射API来访问它。