jdk动态代理-调用栈栈溢出
在 InvocationHandler.invoke() 方法中直接使用 proxy 调用其他方法会导致递归调用,可能引发 StackOverflowError,必须谨慎处理。
UserService proxy = (UserService) Proxy.newProxyInstance(
ProxyUtil.class.getClassLoader(),
new Class[]{UserService.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 错误:直接通过 proxy 调用其他方法 → 递归调用!
proxy.someOtherMethod(); // 会再次触发 invoke,形成无限递归
return method.invoke(userService, args);
}
});
1. 避免直接调用 proxy 的方法
如果需要在 invoke 中调用其他方法,直接调用原始对象(userService)的方法,而不是通过 proxy:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 先执行某些逻辑
System.out.println("Before method: " + method.getName());
// 正确:直接调用原始对象的方法,而不是 proxy
userService.someOtherMethod();
// 执行目标方法
return method.invoke(userService, args);
}
2. 如果必须通过 proxy 调用方法(需特殊处理)
某些场景(如 AOP 拦截)可能需要通过 proxy 调用方法,此时必须避免递归,例如:
-
跳过特定方法(如
toString()、hashCode()) -
使用标志位控制递归
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 避免 toString()/hashCode() 等方法的递归调用
if (method.getName().equals("toString")) {
return "Proxy@" + System.identityHashCode(proxy);
}
// 如果是某些特殊方法,直接调用原始对象
if (method.getName().equals("someOtherMethod")) {
return userService.someOtherMethod();
}
// 其他方法正常代理
System.out.println("拦截方法: " + method.getName());
return method.invoke(userService, args);
}
📌 关键点总结
-
不要直接通过
proxy调用方法,否则会触发invoke递归。 -
优先调用原始对象(
userService)的方法。 -
如果必须用
proxy,需对特定方法(如toString())做特殊处理,或使用标志位控制递归。
这样可以安全地在 InvocationHandler 中实现方法拦截和增强逻辑。

浙公网安备 33010602011771号