应使用 Spring 的 AopProxyUtils.ultimateTargetClass(proxy) 获取 CGLIB 代理的真实目标类,该方法安全兼容多层代理;次选方案是反射获取 CGLIB$CALLBACK_0 中的 target 对象,或调用 proxy.getClass().getSuperclass()(需先确认为 CGLIB 代理且目标类非 final)。

要获取 CGLIB 代理对象背后的真实 Class(即被代理的目标类),不能直接调用 proxy.getClass(),因为返回的是类似 UserService$$EnhancerBySpringCGLIB$$a1b2c3d4 这样的动态生成的子类。需通过 CGLIB 的特殊字段或 Spring 的工具类绕过代理壳。
利用 CGLIB 代理对象的 CGLIB$CALLBACK_0 字段反查目标类
CGLIB 生成的代理类内部通常持有对原始目标对象的引用(尤其在使用 MethodInterceptor 时),且该引用常通过回调(Callback)保存。若代理对象是 Spring 创建的标准 CGLIB 代理(非无目标对象的空代理),可尝试反射读取其内部字段:
- 代理类中一般存在名为
CGLIB$CALLBACK_0的静态字段,类型为MethodInterceptor - 而实际的
MethodInterceptor实现(如 Spring 的DynamicAdvisedInterceptor)内部会持有原始 target 对象 - 可通过反射获取该 callback,再获取其
target或advised属性,最终拿到真实 target 的 class
借助 Spring 的 AopProxyUtils 工具类(推荐)
Spring 提供了开箱即用的工具方法,能安全、兼容地剥离各类代理(包括 JDK 动态代理和 CGLIB),直接返回被代理的目标类:
-
AopProxyUtils.ultimateTargetClass(Object proxy):返回最底层目标对象的 Class(自动处理多层代理) -
AopProxyUtils.getSingletonTarget(Object proxy):返回目标对象实例(若为单例且可访问) - 适用于 Spring 管理的 Bean,内部已适配 CGLIB 和 JDK 两种代理机制
示例:Class<?> actualClass = AopProxyUtils.ultimateTargetClass(proxy);
检查是否为 CGLIB 代理并提取父类(简单但有局限)
如果确定对象是 CGLIB 代理且未做多层增强,可退而求其次——CGLIB 代理类是目标类的子类,因此其直接父类就是目标类:
立即学习“Java免费学习笔记(深入)”;
- 调用
proxy.getClass().getSuperclass()通常能得到原始类(如UserServiceImpl.class) - 注意:若目标类是
final,CGLIB 无法继承,此法失效;Spring 5.2+ 对 final 类默认改用 JDK 代理 - 还需排除
Object.class等异常情况,建议配合ClassUtils.isCglibProxyClass(proxy.getClass())判断
避免手动解析类名(不推荐)
不要用字符串截断方式(如 className.split("\$\$")[0])提取类名再通过 Class.forName() 加载——这容易因包名含 $、类名含特殊字符或类加载器隔离而失败,且破坏封装性。


















