793 字
4 分钟
动态代理
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(); }}它是通过字节码生成技术而不是反射来实现调用的逻辑。