JDK动态代理和CGLIB动态代理源码解析

JDK动态代理源码深度解析 - 基于Proxy的接口代理机制

一、核心原理概述

JDK动态代理是JDK原生支持的代理机制,核心依赖接口与反射 实现。其底层逻辑是:通过 java.lang.reflect.Proxy 类动态生成一个实现目标接口的代理类(字节码),该代理类会将所有方法调用转发给 InvocationHandler 接口的实现类,最终由 InvocationHandler 完成对目标方法的增强与原始调用。 关键限制:JDK动态代理只能代理接口(代理类会实现目标接口),无法直接代理类(除非目标类实现了接口)。

二、核心API源码解析

JDK动态代理的入口是 Proxy.newProxyInstance() 方法,我们从该方法切入,逐步拆解源码流程。

2.1 入口方法:newProxyInstance()

scss 复制代码
public static Object newProxyInstance(ClassLoader var0, Class<?>[] var1, InvocationHandler var2) throws IllegalArgumentException {
    // 1. 校验InvocationHandler不能为空(核心回调,必须指定)
    Objects.requireNonNull(var2);
    // 2. 克隆接口数组:避免外部修改传入的接口数组,保证线程安全
    Class[] var3 = (Class[])var1.clone();
    // 3. 安全管理器检查(若开启,校验调用者是否有生成代理类的权限)
    SecurityManager var4 = System.getSecurityManager();
    if (var4 != null) {
        checkProxyAccess(Reflection.getCallerClass(), var0, var3);
    }
    // 4. 核心步骤:获取/生成代理类的Class对象
    Class var5 = getProxyClass0(var0, var3);
    try {
        // 5. 安全管理器再次检查(校验是否有实例化代理类的权限)
        if (var4 != null) {
            checkNewProxyPermission(Reflection.getCallerClass(), var5);
        }
        // 6. 获取代理类的构造器(参数为InvocationHandler.class)
        final Constructor var6 = var5.getConstructor(constructorParams);
        // 7. 若代理类非public,通过AccessController开放访问权限
        if (!Modifier.isPublic(var5.getModifiers())) {
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    var6.setAccessible(true);
                    return null;
                }
            });
        }
        // 8. 实例化代理类:传入InvocationHandler,返回代理对象
        return var6.newInstance(var2);
    } catch (InstantiationException | IllegalAccessException var8) {
        throw new InternalError(var8.toString(), var8);
    } catch (InvocationTargetException var9) {
        Throwable var7 = var9.getCause();
        if (var7 instanceof RuntimeException) {
            throw (RuntimeException)var7;
        } else {
            throw new InternalError(var7.toString(), var7);
        }
    } catch (NoSuchMethodException var10) {
        throw new InternalError(var10.toString(), var10);
    }
}
关键流程拆解:
  • 参数校验与克隆 :确保 InvocationHandler 非空,克隆接口数组避免外部篡改; - 安全检查:兼容Java安全管理器,控制代理类的生成与实例化权限;
  • 核心逻辑 :通过 getProxyClass0() 获取代理类,再通过构造器实例化(传入 InvocationHandler)。

2.2 代理类缓存:getProxyClass0()

java 复制代码
private static Class<?> getProxyClass0(ClassLoader var0, Class<?>... var1) {
    // 限制:代理的接口数量不能超过65535(JVM类文件格式限制)
    if (var1.length > 65535) {
        throw new IllegalArgumentException("interface limit exceeded");
    } else {
        // 从缓存中获取代理类:key为(类加载器 + 接口数组)
        return (Class)proxyClassCache.get(var0, var1);
    }
}
缓存设计核心:

proxyClassCache 是一个二级缓存(WeakCache),核心作用是避免重复生成代理类。因为: - 相同类加载器 + 相同接口组合,生成的代理类逻辑完全一致; - 缓存key由「类加载器」和「接口数组」组成,确保唯一性。

2.3 缓存获取逻辑:WeakCache.get()

java 复制代码
public V get(K key, P parameter) {
    Objects.requireNonNull(parameter);
    // 清理过期缓存(弱引用相关)
    expungeStaleEntries();
    // 1. 生成一级缓存key(类加载器 + 引用队列)
    Object cacheKey = CacheKey.valueOf(key, refQueue);
    // 2. 获取二级缓存(valuesMap):存储(子key -> 代理类Supplier)
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    if (valuesMap == null) {
        // 若不存在,创建ConcurrentHashMap并放入一级缓存
        ConcurrentMap<Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey, valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }
    // 3. 生成二级缓存key(接口数组相关)
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;
    // 4. 循环尝试获取代理类(处理并发场景)
    while (true) {
        if (supplier != null) {
            // 若supplier存在,获取代理类(可能是缓存的实例或新生成)
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        // 5. 若supplier不存在,创建Factory(用于生成代理类)
        if (factory == null) {
            factory = new Factory(key, parameter, subKey, valuesMap);
        }
        // 6. 尝试将Factory放入二级缓存(CAS操作,保证并发安全)
        if (supplier == null) {
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                // 放入成功,使用当前Factory生成代理类
                supplier = factory;
            }
        } else {
            // 放入失败,替换原有supplier为Factory(重试)
            if (valuesMap.replace(subKey, supplier, factory)) {
                supplier = factory;
            } else {
                supplier = valuesMap.get(subKey);
            }
        }
    }
}
缓存核心逻辑:
  • 一级缓存(map):key是 CacheKey(类加载器 + 引用队列),value是二级缓存 valuesMap
  • 二级缓存(valuesMap):key是 subKey(接口数组相关),value是 Supplier(代理类生成器);
  • 并发安全:通过 ConcurrentHashMap + CAS操作(putIfAbsentreplace)保证多线程下缓存操作安全。

2.4 代理类生成:

  • ProxyClassFactory.apply() 当缓存中无对应代理类时,subKeyFactory(实际是 ProxyClassFactory)的 apply 方法会生成代理类字节码并定义为Class对象。
java 复制代码
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
    // 1. 接口校验:确保接口可见性、是接口、无重复
    Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
    for (Class<?> intf : interfaces) {
        // 校验1:接口必须能被当前类加载器加载(可见性)
        Class<?> interfaceClass = null;
        try {
            interfaceClass = Class.forName(intf.getName(), false, loader);
        } catch (ClassNotFoundException e) {
        }
        if (interfaceClass != intf) {
            throw new IllegalArgumentException(intf + " is not visible from class loader: " + loader);
        }
        // 校验2:必须是接口(JDK代理只能代理接口)
        if (!interfaceClass.isInterface()) {
            throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface");
        }
        // 校验3:接口不能重复
        if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
            throw new IllegalArgumentException("repeated interface: " + interfaceClass.getName());
        }
    }
    // 2. 确定代理类的包名
    String proxyPkg = null;
    int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
    for (Class<?> intf : interfaces) {
        // 若接口是非public的,代理类必须和接口同包(保证访问权限)
        if (!Modifier.isPublic(intf.getModifiers())) {
            accessFlags = Modifier.FINAL;
            // 非public接口的代理类不能是public
            String name = intf.getName();
            int n = name.lastIndexOf('.');
            String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
            if (proxyPkg == null) {
                proxyPkg = pkg;
            } else if (!pkg.equals(proxyPkg)) {
                // 非public接口不能来自不同包
                throw new IllegalArgumentException("non-public interfaces from different packages");
            }
        }
    }
    // 若所有接口都是public,代理类放入默认包:com.sun.proxy
    if (proxyPkg == null) {
        proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
    }
    // 3. 生成代理类名:com.sun.proxy.$Proxy + 自增序号(如$Proxy0)
    long num = nextUniqueNumber.getAndIncrement();
    String proxyName = proxyPkg + proxyClassNamePrefix + num;
    // 4. 核心:生成代理类字节码
    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);
    try {
        // 5. 定义代理类:通过native方法defineClass0将字节码加载为Class对象
        return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);
    } catch (ClassFormatError e) {
        throw new IllegalArgumentException(e.toString());
    }
}
代理类生成关键步骤:
  • 接口校验:确保接口合法(可见、是接口、无重复);
    • 包名与类名 :非public接口同包,public接口用默认包,类名按 $Proxy+序号 生成;
  • 字节码生成ProxyGenerator.generateProxyClass() 生成代理类字节码(核心逻辑,底层是字节码拼接);
  • 类加载 :通过 defineClass0(native方法)将字节码加载为JVM可识别的Class对象。

三、模拟生成JDK代理类源码

JDK动态代理生成的代理类本质是「实现目标接口 + 继承Proxy类」的子类,所有接口方法都会转发给 InvocationHandler.invoke()。以下是模拟代码(以代理 UserService 接口为例):

目标接口:UserService.java

java 复制代码
public interface UserService { 
void addUser(String username); String getUserById(Integer id); 
} 

模拟代理类:$Proxy0.java

java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

/**
 * JDK动态代理生成的代理类模拟(实际由JVM动态生成,并非手动编写)
 */
public final class $Proxy0 extends Proxy implements UserService {
    // 缓存目标接口的方法(避免每次反射获取)
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m4;
    private static Method m0;

    // 构造器:接收InvocationHandler(必须与Proxy类的构造器一致)
    public $Proxy0(InvocationHandler invocationHandler) {
        super(invocationHandler);
    }

    // 重写Object类的equals方法(代理类会代理所有接口方法+Object的equals/hashCode/toString)
    public final boolean equals(Object object) {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{object});
        } catch (RuntimeException | Error runtimeException) {
            throw runtimeException;
        } catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final String toString() {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error runtimeException) {
            throw runtimeException;
        } catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    // 代理UserService的addUser方法
    public final void addUser(String string) {
        try {
            // 核心:转发给InvocationHandler.invoke()
            super.h.invoke(this, m3, new Object[]{string});
        } catch (RuntimeException | Error runtimeException) {
            throw runtimeException;
        } catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    // 代理UserService的getUserById方法
    public final String getUserById(Integer integer) {
        try {
            return (String)super.h.invoke(this, m4, new Object[]{integer});
        } catch (RuntimeException | Error runtimeException) {
            throw runtimeException;
        } catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final int hashCode() {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error runtimeException) {
            throw runtimeException;
        } catch (Throwable throwable) {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    // 静态代码块:初始化方法缓存(类加载时执行)
    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.example.UserService").getMethod("addUser", Class.forName("java.lang.String"));
            m4 = Class.forName("com.example.UserService").getMethod("getUserById", Class.forName("java.lang.Integer"));
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException noSuchMethodException) {
            throw new NoSuchMethodError(noSuchMethodException.getMessage());
        } catch (ClassNotFoundException classNotFoundException) {
            throw new NoClassDefFoundError(classNotFoundException.getMessage());
        }
    }
}
模拟类核心特点:
  1. 继承 Proxy 类(持有 InvocationHandler 引用 h);
  2. 实现目标接口(UserService);
  3. 缓存所有方法(避免每次反射获取,提升性能);
  4. 所有方法调用最终转发给 h.invoke(this, method, args)

四、JDK动态代理总结

  1. 核心依赖:接口 + 反射 + 字节码动态生成;
  2. 代理类特性 :继承 Proxy、实现目标接口、方法转发给 InvocationHandler
  3. 缓存设计 :通过 WeakCache 缓存代理类,避免重复生成;
  4. 限制:只能代理接口,无法代理无接口的类;
  5. 性能:反射调用有一定开销,但缓存方法后性能可接受。

CGLIB动态代理源码解析 - 基于Enhancer的继承代理机制

一、核心原理概述 CGLIB(Code Generation Library)是一个基于ASM字节码框架的动态代理库,

核心依赖继承 实现。其底层逻辑是:通过 Enhancer 类动态生成目标类的子类,重写目标类的非final方法,将方法调用转发给 MethodInterceptor 接口的实现类,最终完成方法增强。 关键优势:无需目标类实现接口,可直接代理类(只要目标类非final、方法非final),弥补了JDK动态代理的限制。

二、核心API源码解析

CGLIB动态代理的核心是 Enhancer 类,我们从其核心配置方法和实例化方法切入,拆解源码流程。

2.1 核心配置:setSuperclass()

  • 设置父类(目标类)
java 复制代码
public void setSuperclass(Class superclass) {
   if (superclass != null && superclass.isInterface()) {
       // 若传入的是接口,转为设置接口(兼容接口代理场景)
       this.setInterfaces(new Class[]{superclass});
       this.setContextClass(superclass);
   } else if (superclass != null && superclass.equals(Object.class)) {
       // 若父类是Object,直接设为null(CGLIB对Object代理有默认处理)
       this.superclass = null;
   } else {
       // 正常设置目标类为父类(核心:代理类将继承该类)
       this.superclass = superclass;
       this.setContextClass(superclass);
   }
}
关键逻辑:
  • CGLIB的核心是「继承代理」,因此 setSuperclass() 是最关键的配置(指定目标类为父类);
  • 兼容接口代理:若传入接口,自动转为 setInterfaces()(但CGLIB更常用於类代理);
  • 限制:目标类不能是final(否则无法继承),方法不能是final(否则无法重写)。

2.2 核心配置:setCallback()

  • 设置回调(增强逻辑)
java 复制代码
  
  public void setCallback(Callback callback) {
  
  // 包装为回调数组(CGLIB支持多回调,setCallback是简化版)
  
  this.setCallbacks(new Callback[]{callback}); 
  } 
  
关键说明:
  • Callback 是CGLIB的回调接口,常用实现类是 MethodInterceptor(方法拦截器); - 多回调支持:setCallbacks() 可传入多个回调,通过 CallbackFilter 指定不同方法使用不同回调; - 核心作用:代理类的方法调用会转发给 Callback 实现类(如 MethodInterceptor.intercept())。

2.3 实例化入口:create()

java 复制代码
public Object create() { // 标记:不仅生成Class,还要实例化对象 
this.classOnly = false; 
// 构造器参数类型:默认无参构造
this.argumentTypes = null;
// 核心:调用createHelper()生成实例
return this.createHelper();
}

2.4 实例化辅助:createHelper()

java 复制代码
private Object createHelper() {
  // 1. 前置校验:检查配置是否合法(如父类是否final、回调是否设置等)
  this.preValidate();
  // 2. 生成缓存key:基于父类、接口、回调类型等关键参数
  Object key = KEY_FACTORY.newInstance(
      this.superclass != null ? this.superclass.getName() : null,
      ReflectUtils.getNames(this.interfaces),
      this.filter == ALL_ZERO ? null : new WeakCacheKey(this.filter),
      this.callbackTypes,
      this.useFactory,
      this.interceptDuringConstruction,
      this.serialVersionUID
  );
  this.currentKey = key;
  // 3. 调用父类(AbstractClassGenerator)的create方法生成实例
  Object result = super.create(key);
  return result;
} 
关键流程拆解:
  • 前置校验preValidate() 检查父类非final、回调非空等核心配置;
  • 缓存key生成:KEY_FACTORY(CGLIB生成的工厂类)基于「父类名、接口名、回调类型、过滤器」等参数生成唯一key,用于缓存代理类;
  • 父类create方法AbstractClassGenerator.create() 是核心,负责生成代理类字节码、加载类、实例化对象。

2.5 缓存与字节码生成(AbstractClassGenerator.create())

CGLIB的缓存逻辑与JDK类似,核心是「避免重复生成代理类」。AbstractClassGeneratorcreate() 方法会:

  1. 从缓存中根据key获取代理类;
  2. 若缓存不存在,通过ASM框架生成代理类字节码;
  3. 调用 ClassLoader 加载代理类;
  4. 通过反射实例化代理类(调用无参构造或指定构造);
  5. 将代理类放入缓存,返回实例。
核心差异(与JDK代理):
  • JDK代理生成的类实现接口,CGLIB生成的类继承目标类;

  • JDK依赖JVM原生字节码生成,CGLIB依赖ASM框架手动拼接字节码;

  • JDK代理转发给 InvocationHandler,CGLIB转发给 MethodInterceptor

    三、模拟生成CGLIB代理类源码

    CGLIB动态代理生成的代理类是「目标类的子类」,重写所有非final方法,通过 MethodInterceptor 实现增强。以下是模拟代码(以代理 UserService 类为例):

    目标类:UserService.java

java 复制代码
/**
* 无接口的目标类(CGLIB可直接代理)
*/
public class UserService {
   public void addUser(String username) {
       System.out.println("目标方法:添加用户 -> " + username);
   }

   public String getUserById(Integer id) {
       System.out.println("目标方法:查询用户 -> " + id);
       return "用户" + id;
   }
}

模拟代理类:EnhancerByCGLIB.java

java 复制代码
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

/**
* CGLIB动态代理生成的代理类模拟(实际由ASM框架动态生成)
*/
public class EnhancerByCGLIB extends UserService {
 // CGLIB生成的方法代理对象(优化反射调用)
 private MethodProxy CGLIB$addUser$0$Proxy;
 private MethodProxy CGLIB$getUserById$1$Proxy;

 // 回调对象(MethodInterceptor)
 private MethodInterceptor CGLIB$CALLBACK_0;

 // 静态代码块:初始化方法代理(ASM生成时自动填充)
 static {
     try {
         // 初始化方法代理:绑定目标方法与代理方法
         Method addUserMethod = UserService.class.getMethod("addUser", String.class);
         Method addUserProxyMethod = UserService$$EnhancerByCGLIB$$123456.class.getMethod("CGLIB$addUser$0", String.class);
         CGLIB$addUser$0$Proxy = MethodProxy.create(
             UserService.class,
             UserService$$EnhancerByCGLIB$$123456.class,
             "(Ljava/lang/String;)V",
             addUserMethod.getName(),
             addUserProxyMethod.getName()
         );

         Method getUserByIdMethod = UserService.class.getMethod("getUserById", Integer.class);
         Method getUserByIdProxyMethod = UserService$$EnhancerByCGLIB$$123456.class.getMethod("CGLIB$getUserById$1", Integer.class);
         CGLIB$getUserById$1$Proxy = MethodProxy.create(
             UserService.class,
             UserService$$EnhancerByCGLIB$$123456.class,
             "(Ljava/lang/Integer;)Ljava/lang/String;",
             getUserByIdMethod.getName(),
             getUserByIdProxyMethod.getName()
         );
     } catch (NoSuchMethodException e) {
         throw new RuntimeException(e);
     }
 }

 // 设置回调(Enhancer通过反射调用该方法注入MethodInterceptor)
 public void setCallback(MethodInterceptor callback) {
     this.CGLIB$CALLBACK_0 = callback;
 }

 // 重写目标类的addUser方法(核心:转发给MethodInterceptor)
 @Override
 public void addUser(String username) {
     MethodInterceptor callback = this.CGLIB$CALLBACK_0;
     if (callback != null) {
         // 调用拦截器:参数(代理对象、目标方法、方法参数、方法代理)
         callback.intercept(this, CGLIB$addUser$0$Proxy.getOriginalMethod(), new Object[]{username}, CGLIB$addUser$0$Proxy);
     } else {
         // 无回调时,直接调用父类(目标类)方法
         super.addUser(username);
     }
 }

 // 重写目标类的getUserById方法
 @Override
 public String getUserById(Integer id) {
     MethodInterceptor callback = this.CGLIB$CALLBACK_0;
     if (callback != null) {
         try {
             return (String) callback.intercept(
                 this,
                 CGLIB$getUserById$1$Proxy.getOriginalMethod(),
                 new Object[]{id},
                 CGLIB$getUserById$1$Proxy
             );
         } catch (Throwable e) {
             throw new RuntimeException(e);
         }
     } else {
         return super.getUserById(id);
     }
 }

 // CGLIB生成的代理方法(内部使用,无需外部调用)
 public void CGLIB$addUser$0(String username) {
     super.addUser(username);
 }

 public String CGLIB$getUserById$1(Integer id) {
     return super.getUserById(id);
 }
}
模拟类核心特点:
  1. 继承目标类(UserService),重写所有非final方法;
  2. 持有 MethodProxy 对象(CGLIB优化反射,通过FastClass机制提升调用性能);
  3. 持有 MethodInterceptor 回调对象,方法调用转发给 intercept()
  4. 提供 setCallback() 方法,供 Enhancer 注入回调。

四、CGLIB动态代理总结

  1. 核心依赖:继承 + ASM字节码框架 + MethodInterceptor;
  2. 代理类特性 :继承目标类、重写非final方法、通过 MethodProxy 优化调用;
  3. 缓存设计:基于「父类、接口、回调类型」等参数缓存代理类,避免重复生成;
  4. 优势 :无需目标类实现接口,支持类代理;通过FastClass机制优化反射性能; 5. 限制:目标类不能是final,方法不能是final(否则无法继承/重写);
相关推荐
月月玩代码2 小时前
SLF4J,简单门面Java日志框架
java·开发语言
用户68545375977692 小时前
布隆过滤器删不掉数据?布谷鸟过滤器:让我来!🐦
后端
isyuah2 小时前
Rust Miko 框架系列(四):深入路由系统
后端·rust
虎子_layor2 小时前
号段模式(分布式ID)上手指南:从原理到实战
java·后端
lkbhua莱克瓦242 小时前
Java基础——集合进阶用到的数据结构知识点3
java·数据结构·github·平衡二叉树·avl
烽学长2 小时前
(附源码)基于Spring boot的校园志愿服务管理系统的设计与实现
java·spring boot·后端
shark_chili2 小时前
硬核安利一个监控告警开源项目Nightingale
后端
拾忆,想起2 小时前
10分钟通关OSI七层模型:从光纤到APP的奇幻之旅
java·redis·网络协议·网络安全·缓存·哈希算法
IT_陈寒2 小时前
WeaveFox 全栈创作体验:从想法到完整应用的零距离
前端·后端·程序员