介紹
ByteBuddy也是一個代碼生成和操作的類庫,可以在運行時動態創建和修改class,底層也是ASM庫,相比於cglib,javassist,Bytebuddy在性能上具有優勢,Hibernate的懶加載和mockito測試框架都使用到了Bytebuddy。官網
實現動態代理
maven依賴
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.10.13</version>
</dependency>
代理接口
/**
* 可以唱歌的
*/
public interface Singable {
/**
* 唱歌
*/
void sing();
}
被代理類
/**
* 歌手
*/
public class Singer implements Singable {
@Override
public void sing() {
System.out.println("I am singing...");
}
}
通過代理接口實現
public class Client {
public static void main(String[] args) throws Exception {
Singable proxy = createByteBuddyDynamicProxy();
proxy.sing();
System.out.println(proxy.toString());
}
private static Singable createByteBuddyDynamicProxy() throws Exception {
return (Singable) new ByteBuddy().subclass(Object.class)
.implement(Singable.class)
.method(ElementMatchers.named("sing"))
.intercept(InvocationHandlerAdapter.of(new SingerInvocationHandler(new Singer())))
.make()
.load(Client.class.getClassLoader())
.getLoaded()
.getDeclaredConstructor()
.newInstance();
}
public static class SingerInvocationHandler implements InvocationHandler {
private Object delegate;
public SingerInvocationHandler(Object delegate) {
this.delegate = delegate;
}
/**
* 動態代理調用方法
*
* @param proxy 生成的代理對象
* @param method 代理的方法
* @param args 方法參數
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("bytebuddy proxy before sing ");
Object ret = method.invoke(delegate, args);
System.out.println("bytebuddy proxy after sing ");
return ret;
}
}
}
繼承Object,實現Singable接口,通過適配JDK的InvocationHandler實現方法的攔截。
public class Client {
public static void main(String[] args) throws Exception {
Singable proxy = createByteBuddyDynamicProxy();
proxy.sing();
System.out.println(proxy.toString());
}
private static Singable createByteBuddyDynamicProxy() throws Exception {
return (Singable) new ByteBuddy().subclass(Object.class)
.implement(Singable.class)
.method(ElementMatchers.named("sing"))
.intercept(MethodDelegation.to(new SingerAgentInterceptor(new Singer())))
.make()
.load(Client.class.getClassLoader())
.getLoaded()
.getDeclaredConstructor()
.newInstance();
}
public static class SingerAgentInterceptor {
private Object delegate;
public SingerAgentInterceptor(Object delegate) {
this.delegate = delegate;
}
/**
* @param proxy 代理對象
* @param method 代理方法
* @param args 方法參數
*/
public Object interceptor(@This Object proxy, @Origin Method method,
@AllArguments Object[] args) throws Exception {
System.out.println("bytebuddy delegate proxy before sing ");
Object ret = method.invoke(delegate, args);
System.out.println("bytebuddy delegate proxy after sing ");
return ret;
}
}
}
我們也可以通過方法委托(MethodDelegation)的方式實現攔截器,
@This 表示生成的代理對象
@Origin 表示被代理的方法
@AllArguments 表示方法參數
通過代理類實現
public class Client {
public static void main(String[] args) throws Exception {
Singable proxy = createByteBuddyDynamicProxy();
proxy.sing();
System.out.println(proxy.toString());
}
private static Singable createByteBuddyDynamicProxy() throws Exception {
return (Singable) new ByteBuddy().subclass(Singer.class)
.implement(Singable.class)
.method(ElementMatchers.named("sing"))
.intercept(MethodDelegation.to(new SingerAgentInterceptor()))
.make()
.load(Client.class.getClassLoader())
.getLoaded()
.getDeclaredConstructor()
.newInstance();
}
public static class SingerAgentInterceptor {
public Object interceptor(@This Object proxy, @Origin Method method,
@SuperMethod Method superMethod,
@AllArguments Object[] args) throws Exception {
System.out.println("bytebuddy delegate proxy2 before sing ");
Object ret = superMethod.invoke(proxy, args);
System.out.println("bytebuddy delegate proxy2 after sing ");
return ret;
}
}
}
繼承Singer類,@SuperMethod 表示父類的方法。