793 字
4 分钟
动态代理
2025-11-03
无标签

JDK动态代理与CGLIB动态代理的区别?#

回答重点#

JDK 动态代理:基于接口实现,所以要求代理类一定是有定义接口的。 CGLIB:基于 ASM 字节码生成工具,通过继承的方式生成目标类的子类来实现代理类,因此要注意目标类中的 final 方法(final 方法无法被重写,会导致代理失效)。

性能对比(随 JDK 版本变化)

  • JDK 6:调用次数较少时,JDK 动态代理与 CGLIB 性能差距不明显,甚至 JDK 动态代理更快;调用次数增加后,CGLIB 表现稍快。
  • JDK 7:情况反转,调用次数少(1,000,000 次内)时,JDK 动态代理比 CGLIB 快约 30%;调用次数多(50,000,000 次以上)时,-JDK 动态代理快近 1 倍。
  • JDK 8:表现与 JDK 7 基本一致。

扩展JDK动态代理#

JDK动态代理是基于接口的代理,因此要求代理类一定是有定义的接口,使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler实现。

下面是JDK动态代理实例

// 接口
public interface Service {
void perform();
}
// 需要被代理的实现类
public class ServiceImpl implements Service {
@Override
public void perform() {
System.out.println("mianshiya.com");
}
}
//JDK动态代理处理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
// 自定义调用处理器,实现 InvocationHandler 接口
public class ServiceInvocationHandler implements InvocationHandler {
//被代理的处理对象(即真实的业务对象)
private final Object target;
//构造方法:传入被代理的目标对象
public ServiceInvocationHandler(Object target) {
this.target = target;
}
// 核心方法:拦截代理对象的方法调用,并执行自定义逻辑
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 方法调用前的增强逻辑(如日志、权限校验)
System.out.println("Before method invoke");
// 调用目标对象的原始方法(通过反射执行)
Object result = method.invoke(target, args);
// 方法调用后的增强逻辑(如事务提交、结果处理)
System.out.println("After method invoke");
return result;
}
}
import java.lang.reflect.Proxy;
//创建并使用动态代理对象
public class DynamicProxyDemo {
public static void main(String[] args) {
Service target = new ServiceImpl();
Service proxy = (Service) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new ServiceInvocationHandler(target)
);
proxy.perform();
}
}
  • 首先通过实现 InvocationHandler 接口得到一个切面类。
  • 然后利用 Proxy 根据目标类的类加载器、接口和切面类得到一个代理类。
  • 代理类的逻辑就是把所有接口方法的调用转发到切面类的 invoke() 方法上,然后根据反射调用目标类的方法。

扩展CGLIB动态代理#

CGLIB基于 ASM 字节码生成工具,他是通过继承来实现代理类的,所以不需要接口,可以代理普通类,但要注意final方法(不可继承)。

public class Service {
public void perform() {
System.out.println("mianshiya.com");
}
}
//CGLIB动态处理代理类
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class ServiceMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method invoke");
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method invoke");
return result;
}
}
//创建并使用动态代理对象
import net.sf.cglib.proxy.Enhancer;
public class CglibDynamicProxyDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Service.class);
enhancer.setCallback(new ServiceMethodInterceptor());
Service proxy = (Service) enhancer.create();
proxy.perform();
}
}

它是通过字节码生成技术而不是反射来实现调用的逻辑。

动态代理
https://www.fdssong.js.cn/posts/动态代理/
作者
FDSSONG
发布于
2025-11-03
许可协议
CC BY-NC-SA 4.0