ByteBuddy实现动态代理
介绍
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 表示父类的方法。