<
groupId
>
net
.
bytebuddy
<
/
groupId
>
<
artifactId
>
byte
-
buddy
<
/
artifactId
>
<
version
>
1.12
.13
<
/
version
>
<
/
dependency
>
方法代理:类似与SpringAOP,创建一个代理对象,去调用目标方法。bytebuddy的方法代理是在目标方法中调用代理类的方法,然后再回调的本类的源方法。
public class UserService {
public String selectUser(String username) {
return "张三";
public class AgentMain {
public static void premain(String agentArgs, Instrumentation instrumentation) {
AgentBuilder.Transformer transformer = new AgentBuilder.Transformer() {
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
ClassLoader classLoader, JavaModule module, ProtectionDomain protectionDomain) {
return builder.method(ElementMatchers.named("selectUser"))
.intercept(MethodDelegation.to(AgentMain.Interceptor.class));
new AgentBuilder.Default()
.ignore(nameStartsWith("net.bytebuddy."))
.type(ElementMatchers.named("com.liuqi.service.UserService"))
.transform(transformer)
.with(new AgentBuilder.Listener() {
public void onDiscovery(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) {}
public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, boolean loaded, DynamicType dynamicType) {
String className = typeDescription.getName();
System.out.println("增强类: " + className);
public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, boolean loaded) {}
public void onError(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded, Throwable throwable) {
System.out.println("增强类失败: " + typeName + "; 失败原因: " + throwable);
public void onComplete(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) { }
.installOn(instrumentation);
instrumentation.addTransformer(new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
if (className.contains("UserService")) {
try {
String substring = className.substring(className.lastIndexOf("/"));
Files.write(new File("C:/Users/86187/Desktop/bytebuddy-class/" + substring + ".class").toPath(), classfileBuffer);
} catch (IOException e) {
e.printStackTrace();
return classfileBuffer;
});
public static class Interceptor {
@RuntimeType
public static Object intercept(@This Object target,
@AllArguments Object[] allArguments,
@SuperCall Callable<?> superCall,
@Origin Method method
) throws Throwable {
Object result = null;
try {
System.out.println("前置拦截");
result = superCall.call();
return result;
} catch (Throwable t) {
System.out.println("异常拦截");
throw t;
} finally {
System.out.println("后置拦截: 方法返回值 = " + result);
查看增强后的类
可以看到bytebuddy
为UserService类又生成了一个类。
反编译 UserService
类
标注synthetic
说明是编译器生成的。
package com.liuqi.service;
import com.liuqi.agent.AgentMain.Interceptor;
import com.liuqi.service.UserService.auxiliary.VdebFR3h;
import java.lang.reflect.Method;
public class UserService {
private static final Method cachedValue$wCBkyXnP$fi9hdm2;
public String selectUser(String var1) {
return (String)Interceptor.intercept(
this,
new Object[]{var1},
new VdebFR3h(this, var1),
cachedValue$wCBkyXnP$fi9hdm2
private String selectUser$original$uTSGTdQZ(String username) {
return "张三";
static {
ClassLoader.getSystemClassLoader().loadClass("net.bytebuddy.dynamic.Nexus").getMethod("initialize", new Class[]{Class.class, Integer.TYPE}).invoke((Object)null, new Object[]{UserService.class, Integer.valueOf(-449407519)});
cachedValue$wCBkyXnP$fi9hdm2 = UserService.class.getMethod("selectUser", new Class[]{String.class});
final String selectUser$original$uTSGTdQZ$accessor$wCBkyXnP(String var1) {
return this.selectUser$original$uTSGTdQZ(var1);
反编译 UserService
import com.liuqi.service.UserService;
import java.util.concurrent.Callable;
class UserService$auxiliary$VdebFR3h implements Runnable, Callable {
private UserService argument0;
private String argument1;
public Object call() throws Exception {
return this.argument0.selectUser$original$uTSGTdQZ$accessor$wCBkyXnP(this.argument1);
public void run() {
this.argument0.selectUser$original$uTSGTdQZ$accessor$wCBkyXnP(this.argument1);
UserService$auxiliary$VdebFR3h(UserService var1, String var2) {
this.argument0 = var1;
this.argument1 = var2;
自定义一个类。
public interface MyCallable {
* 定义一个方法, 方法名随意 {此类中只能有这一个方法, 只能有一个入参}
* @param args 方法入参
* @return
Object call(Object[] args);
在设置拦截器时,写入以下配置:
MethodDelegation.withDefaultConfiguration().withBinders(Morph.Binder.install(MyCallable.class))
AgentBuilder.Transformer transformer = new AgentBuilder.Transformer() {
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
ClassLoader classLoader, JavaModule module, ProtectionDomain protectionDomain) {
return builder.method(ElementMatchers.named("selectUser"))
.intercept(MethodDelegation.withDefaultConfiguration()
.withBinders(Morph.Binder.install(MyCallable.class))
.to(AgentMain.Interceptor.class));
拦截器修改以下配置:
使用@Morph MyCallable
接收代理对象
public static class Interceptor {
@RuntimeType
public static Object intercept(@This Object target,
@AllArguments Object[] allArguments,
@Origin Method method,
@Morph MyCallable superCall
) throws Throwable {
Object result = null;
try {
System.out.println("前置拦截");
allArguments[0] = "1111";
result = superCall.call(allArguments);
return result;
} catch (Throwable t) {
System.out.println("异常拦截");
throw t;
} finally {
System.out.println("后置拦截: 方法返回值 = " + result);
创建拦截器
package com.liuqi.agent;
import net.bytebuddy.asm.Advice;
import java.lang.reflect.Method;
* @author liuqi
* @date 2022/12/15 12:27
* @since 1.0.0
public class AdviceInterceptor {
* 方法运行前: 执行代码的片段, 必须是静态的方法
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void enter(@Advice.This Object that,
@Advice.AllArguments Object[] args,
@Advice.Origin Method method)
System.out.println("前置拦截 ");
* 方法退出前, 代码执行片段, 必须是静态的方法
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void exit(@Advice.This Object that,
@Advice.AllArguments Object[] args,
@Advice.Origin Method method,
@Advice.Return Object result,
@Advice.Thrown Throwable t
if (t != null) {
System.out.println("异常拦截");
} else {
System.out.println("后置拦截 ");
设置拦截器
在transform
方法中填写new AgentBuilder.Transformer.ForAdvice()
实例。
advice
方法中有两个入参:
new AgentBuilder.Default()
.ignore(nameStartsWith("net.bytebuddy."))
.type(ElementMatchers.named("com.liuqi.service.UserService"))
.transform(
new AgentBuilder.Transformer.ForAdvice()
.advice(ElementMatchers.named("selectUser"), "com.liuqi.agent.AdviceInterceptor")
.installOn(instrumentation);
查看增强后的类
可以看到bytebuddy
没有生成其他的代理类。
反编译 UserService
类
可以看到,此增强方式,是将拦截器中的代码直接拷贝至此方法中
。
package com.liuqi.service;
public class UserService {
public String selectUser(String var1) {
try {
System.out.println("前置拦截 ");
} catch (Throwable var7) {
String var2;
Throwable username;
label31: {
String var10000;
try {
var10000 = "张三";
} catch (Throwable var8) {
username = var8;
var2 = null;
break label31;
var2 = var10000;
username = null;
try {
if(username != null) {
System.out.println("异常拦截");
} else {
System.out.println("后置拦截 ");
} catch (Throwable var6) {
if(username != null) {
throw username;
} else {
return var2;
static {
ClassLoader.getSystemClassLoader().loadClass("net.bytebuddy.dynamic.Nexus").getMethod("initialize", new Class[]{Class.class, Integer.TYPE}).invoke((Object)null, new Object[]{UserService.class, Integer.valueOf(250183171)});
方法代理的方式,会为每个方法增强都会生成一个代理对象。例如一个类中,需要增强两个方法,则会生成两个代理类。
skywalking
是使用此方式。
字节码方法修改
此方式只是将代理类的执行代码拷贝至目标方法中,并不会生成额外的代理类。即使一个类中增强了多个方法。
OpenTelemetry
使用此方式。