InvocationHandler.invoke 是 Java 动态代理的核心回调入口,负责统一分发代理对象的方法调用;它不依赖反射,仅在需执行目标方法时才可能通过 Method.invoke 触发反射,其本质是代理机制设计的拦截点而非反射监听器。

InvocationHandler.invoke 是 Java 动态代理的核心入口,所有被代理接口的方法调用最终都会进入这个方法。它不是“反射调用”的拦截器,而是代理对象方法调用的统一分发点;真正执行目标方法时,才可能用到反射(比如通过 Method.invoke),但拦截本身不依赖反射——它是代理机制设计的回调。
拦截发生在代理对象调用时,而非反射调用时
动态代理(Proxy.newProxyInstance)生成的是一个实现了指定接口的代理类实例,它没有继承目标类,也不修改字节码。当你调用代理对象的方法(如 proxy.doSomething()),JVM 会把该调用转给 InvocationHandler.invoke,而不是直接执行目标方法。此时你拿到的是:
- Object proxy:代理对象本身
- Method method:被调用的接口方法(注意:是接口声明的方法,不是实现类的方法)
- Object[] args:传入的参数数组
这时候还没触发任何反射调用,更没执行目标方法——你完全可以在 invoke 中决定:
- 直接返回 mock 值(跳过真实调用)
- 记录日志、统计耗时、校验参数
- 检查权限或事务上下文
- 调用真实目标(这时才可能用 method.invoke(target, args))
增强逻辑写在 invoke 方法里,不是靠“监听反射”
所谓“增强”,就是围绕目标方法执行前后插入自定义逻辑。典型结构如下:
- 前置处理:如打印开始时间、校验参数合法性
- 执行目标方法:通常用
method.invoke(target, args)—— 这一步才是真正的反射调用 - 后置处理:如计算耗时、捕获异常、记录返回值或错误日志
注意:target 需要你自己持有(比如构造时传入),InvocationHandler 不知道也不管理目标对象,它只负责分发调用。
常见增强场景与写法示例
比如加日志和耗时统计:
立即学习“Java免费学习笔记(深入)”;
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("【开始】调用 " + method.getName());
long start = System.nanoTime();
try {
Object result = method.invoke(target, args); // 真正的反射调用在此
long cost = System.nanoTime() - start;
System.out.println("【完成】" + method.getName() + ",耗时:" + cost + "ns");
return result;
} catch (InvocationTargetException e) {
throw e.getTargetException(); // 包装异常,暴露原始异常
}
}再比如权限控制:
- 检查 method 上是否有
@RequireRole("ADMIN")注解 - 从 ThreadLocal 获取当前用户角色
- 不满足则抛出
SecurityException,根本不会走到method.invoke
和反射 API 的关系要分清
Method.invoke 是反射工具,用于运行时调用任意方法;InvocationHandler.invoke 是代理协议回调,属于 JDK 动态代理框架的一部分。两者常配合使用,但职责不同:
- 你想拦截谁调用了接口方法 → 用 InvocationHandler
- 你想在运行时调用某个不确定的方法 → 用 Method.invoke
它们可以独立存在:你可以用 InvocationHandler 返回固定值而不调用任何反射;也可以用反射直接调方法,完全不用代理。
不复杂但容易忽略。


















