jdk动态代理无法直接获取目标对象,需在invocationhandler中显式保存;cglib代理可通过反射或advised接口安全获取目标对象,spring aop推荐使用expose-proxy=true配合gettargetsource().gettarget()。

Java 动态代理本身不直接暴露被代理的目标对象,因为代理对象(如 Proxy 实例)和目标对象是两个独立实例,代理仅持有对目标的引用(如果设计上有的话)。能否获取真实目标对象,取决于代理的实现方式——JDK 动态代理无法直接获取目标对象,而 CGLIB 代理在特定条件下可以。
JDK 动态代理:目标对象通常不可直接获取
JDK 代理基于接口,通过 Proxy.newProxyInstance() 创建代理对象,其内部使用 InvocationHandler 拦截方法调用。但 InvocationHandler 是用户传入的,是否持有目标对象完全由你决定:
- 如果你在
InvocationHandler实现中显式保存了目标对象(常见做法),就可以安全访问它 - 如果没保存(比如只做日志或权限校验,不转发调用),那目标对象可能根本不存在或已被 GC
-
Proxy.getInvocationHandler(proxy)可以拿到 handler,但 handler 本身不保证包含目标对象——得看你的代码怎么写的
CGLIB 代理:可通过特殊字段获取目标对象
CGLIB 基于继承,生成目标类的子类。它默认会在代理对象中添加一个名为 CGLIB$CALLBACK_0 的字段(类型为 MethodInterceptor),而这个拦截器通常持有一个对原始目标对象的引用(尤其在使用 Enhancer.setCallback() 配合自定义 MethodInterceptor 时):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 你可以通过反射读取代理对象的
callback字段(如MethodInterceptor实例) - 若该拦截器是你自己编写的(例如继承
MethodInterceptor并在构造时传入 target),就能直接返回目标对象 - 注意:Spring AOP 默认使用的 CGLIB 代理中,
Advised接口提供了getTargetSource().getTarget()方法,这是推荐的安全方式(需强转为Advised)
通用建议:主动管理目标引用,而非反向挖掘
依赖反射“挖”代理背后的 target 容易出错、耦合框架实现、且在 Spring 等容器中可能因代理链嵌套(如事务+缓存多层代理)而失效:
- 在创建代理时,把目标对象作为参数传给 handler 或 interceptor,并提供公共 getter 方法
- 在 Spring 中,优先使用
AopContext.currentProxy()获取当前代理,再通过Advised接口获取 target(确保expose-proxy=true) - 避免在业务逻辑中强行解包代理——这往往说明设计上应将 target 作为上下文显式传递,而不是靠代理“猜”
Spring AOP 场景下的安全获取方式
如果你用的是 Spring AOP(无论 JDK 还是 CGLIB):
- 确认配置了
<config expose-proxy="true"></config>或@EnableAspectJAutoProxy(exposeProxy = true) - 在目标类内部需要访问自身 target 时,用
((Advised) AopContext.currentProxy()).getTargetSource().getTarget() - 注意:该方式仅适用于同一对象内 self-invocation 场景,且 target 必须是非 singleton 或可获取的
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










