动态代理
简介
动态代理在java中有着广泛的应用。比如Spring AOP、Hibernate数据查询、测试框架的后端mock、RPC远程调用、Java注解对象获取、日志、用户鉴权、全局性异常处理、性能监控,甚至事务处理等。
静态代理
假如有1个接口,如下:
public interface OrderService {
void create(int id);
void pay(int id);
}实现为:
public class OrderServiceImpl implements OrderService {
@Override
public void create(int id) {
System.out.println("create order");
}
@Override
public void pay(int id) {
System.out.println("pay order");
}
}使用静态代理对其增强
import java.util.Date;
/**
* 静态代理
*
* @author dcx
* @since 2023-06-21 10:04
**/
public class OrderServiceProxy implements OrderService {
//被代理的对象
private OrderService orderService;
public OrderServiceProxy(OrderService orderService) {
this.orderService = orderService;
}
@Override
public void create(int id) {
before();
orderService.create(id);
after();
}
@Override
public void pay(int id) {
before();
orderService.pay(id);
after();
}
private void before() {
System.out.println("before: " + new Date());
}
private void after() {
System.out.println("after: " + new Date());
}
}使用
public static void staticProxy() {
//生成被代理对象
OrderService orderService = new OrderServiceImpl();
//生成代理对象
OrderServiceProxy orderServiceProxy = new OrderServiceProxy(orderService);
//代理对象执行
orderServiceProxy.create(1);
orderServiceProxy.pay(1);
}优点
这样就在不侵入原先代码的情况下,对原有对象进行了增强。
不足
新增,删除方法时,需要同时修改目标类和代理类。
当代理多个类的时候,造成代码混乱。
思考
代理类是根据目标类产生,有一定的规律。有没有什么办法在类加载阶段完成代理类的自动生成呢?
介绍2种现成的实现:
通过实现接口生成代理类。-->JDK动态代理。
通过继承生成代理类-->CGLib。
JDK动态代理
通过实现 InvocationHandler,生成代理处理器。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Date;
/**
* jdk 动态代理,实现日志打印
*
* @author dcx
* @since 2023-06-21 10:12
**/
public class LogHandler implements InvocationHandler {
//被代理的对象
Object target;
public LogHandler(Object target) {
this.target = target;
}
/**
* 反射对象
* @param proxy 代理对象
* @param method 代理的方法
* @param args 方法入参
* @return java.lang.Object 方法执行结果
* @author dcx
* @date 2023/6/21 10:15
**/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target, args);
after();
return result;
}
private void before() {
System.out.println("before: " + new Date());
}
private void after() {
System.out.println("after: " + new Date());
}
}使用
public static void jdkProxy(){
//目标类
OrderService orderService = new OrderServiceImpl();
//获取类加载器
ClassLoader classLoader = orderService.getClass().getClassLoader();
//获取对象实现的接口类,OrderServiceImpl实现的是OrderService接口类
Class<?>[] interfaces = orderService.getClass().getInterfaces();
//创建代理处理器
LogHandler logHandler = new LogHandler(orderService);
//创建代理对象
OrderService orderServiceProxy = (OrderService) Proxy.newProxyInstance(classLoader, interfaces, logHandler);
//代理对象执行方法
orderServiceProxy.create(1);
orderServiceProxy.pay(1);
//输出代理对象class文件
ProxyUtils.generateClassFile(orderService.getClass(),"OrderServiceImpljdkProxy");
}查看下生成的代理类
import com.skuu.proxy.OrderService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class OrderServiceImpljdkProxy extends Proxy implements OrderService {
private static Method m1;
private static Method m4;
private static Method m2;
private static Method m3;
private static Method m0;
public OrderServiceImpljdkProxy(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void create(int var1) throws {
try {
super.h.invoke(this, m4, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void pay(int var1) throws {
try {
super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m4 = Class.forName("com.skuu.proxy.OrderService").getMethod("create", Integer.TYPE);
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.skuu.proxy.OrderService").getMethod("pay", Integer.TYPE);
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}代理类继承了 Proxy 类,并且实现了被代理的所有接口,以及equals、hashCode、toString等方法。
类和所有方法都被
public final修饰,所以代理类只可被使用,不可以再被继承。目标类的每个方法,在代理类中通过反射生成Method对象。
每个方法中的
super.h都是之前设置的代理控制器(LogHandler),来执行真正的逻辑。
代理对象UML

可以看出,代理对象执行方法时,会通过继承于父类的InvocationHandler来调用代理控制器,最终调用目标类的方法。
CGLIB动态代理
目标类
public class Order {
public void create(int id) {
System.out.println("create");
}
public void pay(int id) {
System.out.println("pay");
}
}日志拦截器
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
import java.util.Date;
/**
* cglib动态代理处理
*
* @author dcx
* @since 2023-06-21 10:59
**/
public class LogInterceptor implements MethodInterceptor {
/**
* 对象执行拦截
*
* @param o 被代理的对象
* @param method 拦截的方法
* @param objects 参数列表
* @param methodProxy 对方法的代理
* @return java.lang.Object
* @author dcx
* @date 2023/6/21 11:00
**/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
// 注意这里是调用 invokeSuper 而不是 invoke,否则死循环,methodProxy.invokesuper执行的是原始类的方法,method.invoke执行的是子类的方法
Object result = methodProxy.invokeSuper(o, objects);
after();
return result;
}
private void before() {
System.out.println("before: " + new Date());
}
private void after() {
System.out.println("after: " + new Date());
}
}使用
public static void cglibProxy(){
//生成拦截处理器
LogInterceptor logInterceptor = new LogInterceptor();
//方法增强处理类
Enhancer enhancer = new Enhancer();
//设置超类
enhancer.setSuperclass(Order.class);
//设置回调时拦截增强
enhancer.setCallback(logInterceptor);
//创建增强类
Order order = (Order) enhancer.create();
order.create(1);
order.pay(1);
}查找目标类上的所有非final 的public类型的方法定义;
将这些方法的定义转换成字节码;
将组成的字节码转换成相应的代理的class对象;
实现 MethodInterceptor接口,用来处理对代理类上所有方法的请求。
JDK动态代理与CGLIB动态代理对比
JDK动态代理:基于Java反射机制实现,必须要实现了接口的业务类才能用这种办法生成代理对象。
cglib动态代理:基于ASM机制实现,通过生成业务类的子类作为代理类。
推荐使用:如spring一般,如果目标类实现了接口,就用jdk动态代理,反之则用cglib。
Last updated
Was this helpful?