拦截来自特定命名空间的所有 methods/construtors/getters/setters
Intercept all methods/construtors/getters/setters from a specific namespace
我有一个 Java 代理是这样实现的:
public static void premain(String args, Instrumentation instrumentation) throws ClassNotFoundException {
new AgentBuilder.Default()
.type(isSubTypeOf(Object.class).and(nameStartsWith("com.my.domain")))
.transform(new Transformer5())
.installOn(instrumentation);
}
然后转换 class:
public class Transformer5 implements AgentBuilder.Transformer {
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader) {
return builder.method(any().and(isDeclaredBy(typeDescription)))
.intercept(MethodDelegation.to(Interc4.class));
}
}
和拦截器:
public class Interc4 {
static String indent = "";
@RuntimeType
@BindingPriority(BindingPriority.DEFAULT * 3)
public static Object intercept(@SuperCall Callable<?> zuper,
@AllArguments Object[] allArguments,
@Origin String method) throws Exception {
System.out.println(indent + "Intercepted4 M" + method);
try {
indent += " ";
return zuper.call();
} finally {
//post process
indent = indent.substring(0, indent.length()-2);
}
}
}
这个问题是它不拦截构造函数,它也会给出这种错误
Cannot define non-public or non-virtual method 'lambda$static' for interface type
制作拦截器的最佳方法是什么,该拦截器将代理来自某个域的 class 中的每个方法(我希望能够获取方法名称,检查方法参数(如果有)并直接转发执行)。
发生这种情况有两个原因。
Cannot define non-public or non-virtual method 'lambda$static' for interface type
是由 Byte Buddy 中的验证错误引起的。我将在下一个版本中修复此问题。同时,您可以通过 new AgentBuilder.Default(new ByteBuddy().with(TypeValidation.DISABLED))
.
禁用验证
您明确地只拦截通过 .method( ... )
匹配的方法。您可以通过 .constructor( ... )
拦截构造函数或通过 .invokable( ... )
拦截任何可调用的构造函数。但是,您将无法将拦截器用于必须对超级方法调用进行硬编码的构造函数。但是,您可以将拦截器分成两部分:
class Interceptor {
public static void before() { ... }
public static void after() { ... }
}
使用
.intercept(MethodDelegation.to(Interceptor.class).filter(named("before")
.andThen(SuperMethodCall.INSTANCE
.andThen(MethodDelegation.to(Interceptor.class).filter(named("after"))))
这样,Byte Buddy 可以对超级构造函数调用进行硬编码,同时触发 before
和 after
方法。请注意,@This
注释不适用于 before
方法。
我有一个 Java 代理是这样实现的:
public static void premain(String args, Instrumentation instrumentation) throws ClassNotFoundException {
new AgentBuilder.Default()
.type(isSubTypeOf(Object.class).and(nameStartsWith("com.my.domain")))
.transform(new Transformer5())
.installOn(instrumentation);
}
然后转换 class:
public class Transformer5 implements AgentBuilder.Transformer {
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader) {
return builder.method(any().and(isDeclaredBy(typeDescription)))
.intercept(MethodDelegation.to(Interc4.class));
}
}
和拦截器:
public class Interc4 {
static String indent = "";
@RuntimeType
@BindingPriority(BindingPriority.DEFAULT * 3)
public static Object intercept(@SuperCall Callable<?> zuper,
@AllArguments Object[] allArguments,
@Origin String method) throws Exception {
System.out.println(indent + "Intercepted4 M" + method);
try {
indent += " ";
return zuper.call();
} finally {
//post process
indent = indent.substring(0, indent.length()-2);
}
}
}
这个问题是它不拦截构造函数,它也会给出这种错误
Cannot define non-public or non-virtual method 'lambda$static' for interface type
制作拦截器的最佳方法是什么,该拦截器将代理来自某个域的 class 中的每个方法(我希望能够获取方法名称,检查方法参数(如果有)并直接转发执行)。
发生这种情况有两个原因。
Cannot define non-public or non-virtual method 'lambda$static' for interface type
是由 Byte Buddy 中的验证错误引起的。我将在下一个版本中修复此问题。同时,您可以通过new AgentBuilder.Default(new ByteBuddy().with(TypeValidation.DISABLED))
. 禁用验证
您明确地只拦截通过
.method( ... )
匹配的方法。您可以通过.constructor( ... )
拦截构造函数或通过.invokable( ... )
拦截任何可调用的构造函数。但是,您将无法将拦截器用于必须对超级方法调用进行硬编码的构造函数。但是,您可以将拦截器分成两部分:class Interceptor { public static void before() { ... } public static void after() { ... } }
使用
.intercept(MethodDelegation.to(Interceptor.class).filter(named("before") .andThen(SuperMethodCall.INSTANCE .andThen(MethodDelegation.to(Interceptor.class).filter(named("after"))))
这样,Byte Buddy 可以对超级构造函数调用进行硬编码,同时触发 before
和 after
方法。请注意,@This
注释不适用于 before
方法。