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);
}

 

📌 关键点总结

  1. 不要直接通过 proxy 调用方法,否则会触发 invoke 递归。

  2. 优先调用原始对象(userService)的方法

  3. 如果必须用 proxy,需对特定方法(如 toString())做特殊处理,或使用标志位控制递归。

这样可以安全地在 InvocationHandler 中实现方法拦截和增强逻辑。

posted @ 2025-05-27 19:28  阿瞒123  阅读(15)  评论(0)    收藏  举报