JDK动态代理是Java提供的基于接口的运行时代理机制,通过Proxy.newProxyInstance生成代理对象,所有方法调用均被转发至InvocationHandler.invoke()统一拦截处理,从而实现AOP功能。

Java 反射本身不直接参与 Proxy.newProxyInstance 的代理创建,真正起作用的是 Java 的动态代理机制(基于接口的 JDK Proxy),它底层依赖反射来调用目标方法,但 Proxy 类的生成和字节码操作由 JVM 在运行时完成,不是纯反射调用。要实现 AOP 拦截,核心是通过 InvocationHandler 统一拦截所有接口方法调用,在其中织入前置、后置、异常等逻辑。
1. 代理对象必须基于接口,不能代理类
JDK 动态代理只支持对接口生成代理实例。如果你有一个接口 UserService,可以为其创建代理;但对 UserServiceImpl 这样的具体类,JDK Proxy 无法直接代理(需用 CGLIB 或 Javassist)。
- 确保目标对象实现了至少一个接口
- 代理对象的类型就是该接口类型,不是实现类类型
- 调用方必须面向接口编程(例如用
UserService引用,而非UserServiceImpl)
2. 编写 InvocationHandler 实现拦截逻辑
这是 AOP 的核心:所有被代理接口的方法调用,都会进入 invoke 方法。你可以在其中添加日志、权限校验、事务控制、性能统计等横切关注点。
示例:
立即学习“Java免费学习笔记(深入)”;
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
public class LoggingInvocationHandler implements InvocationHandler {
private final Object target; // 真实目标对象
public LoggingInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("【前置】调用方法: " + method.getName());
Object result = null;
try {
result = method.invoke(target, args); // 反射调用真实方法
System.out.println("【返回】结果: " + result);
return result;
} catch (Exception e) {
System.out.println("【异常】" + e.getMessage());
throw e;
} finally {
System.out.println("【后置】方法执行完毕");
}
}
}
-
proxy是生成的代理对象(仅用于识别,一般不用) -
method是被调用的方法对象,可获取注解、参数类型等元信息 -
method.invoke(target, args)是关键反射调用,触发真实业务逻辑 - 可在 try/catch/finally 中自由组织 AOP 行为
3. 使用 Proxy.newProxyInstance 创建代理实例
需要三个参数:类加载器、代理要实现的接口数组、InvocationHandler 实例。
示例:
立即学习“Java免费学习笔记(深入)”;
UserService realService = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(), // 类加载器
new Class[]{UserService.class}, // 接口数组(必须!)
new LoggingInvocationHandler(realService) // 拦截处理器
);
proxy.getUser(123); // 所有调用都会经过 LoggingInvocationHandler.invoke()
- 类加载器建议用目标接口或目标类的类加载器,避免 ClassCastException
- 接口数组可传多个,代理对象将同时实现它们
- 返回值是
Object,需强制转为对应接口类型(不能转为实现类)
4. 结合反射增强 AOP 灵活性
虽然 Proxy 本身不靠反射生成字节码,但 InvocationHandler 内常配合反射做元数据检查,比如:
- 用
method.isAnnotationPresent(Transactional.class)判断是否开启事务 - 用
method.getParameterAnnotations()提取自定义注解参数 - 用
target.getClass().getMethod(...)获取桥接方法或泛型信息 - 用
MethodHandles.lookup()(Java 7+)提升反射调用性能(可选优化)
这些反射操作发生在拦截过程中,不影响代理创建,但让 AOP 更智能、更通用。

















