java动态代理通过proxy.newproxyinstance生成代理对象,由invocationhandler.invoke()统一拦截并反射调用目标方法;default方法默认不被代理,需重写或改用cglib;$proxy类无法通过class.forname加载。

Java 动态代理中,方法的拦截和调用不是靠“手动反射创建代理类”,而是由 Proxy.newProxyInstance 自动生成代理对象,并统一交由 InvocationHandler.invoke() 处理——真正用到反射的地方,是在这个 invoke 方法里调用目标对象的原始方法。
拦截发生在 InvocationHandler.invoke() 中
每次通过代理对象调用接口方法,JVM 都不会执行原逻辑,而是转到你写的 invoke 方法。这里三个参数很关键:
- proxy:生成的代理对象(如 $Proxy0),一般不用直接操作
- method:被调用的方法对象,含名称、参数类型、返回值等元信息
-
args:已解包的实际参数数组(比如传了
"zhangsan",这里就是new Object[]{"zhangsan"})
调用目标方法必须用 method.invoke(target, args)
这是反射调用的核心步骤。不能写 target.xxx(args),否则就失去动态性,也绕过了代理机制:
- target 是你传入的真实对象(如 UserServiceImpl 实例)
- method 是从接口上获取的 Method 对象,代表当前被调用的方法
- args 直接透传即可,基本类型会自动拆箱,无需额外处理
- 异常必须处理:method.invoke 抛出
InvocationTargetException,要用e.getCause()提取原始异常再抛出,否则堆栈不清晰
默认方法(default method)不会被自动代理
即使接口定义了 default 方法,JDK 动态代理默认不拦截它——调用时会直接报 AbstractMethodError。解决办法只有两个:
- 让实现类重写该 default 方法,确保它出现在
target.getClass().getDeclaredMethods()中 - 或改用 CGLIB(但那就不是 JDK 代理了)
为什么不能用 Class.forName + newInstance 创建代理?
因为代理类(如 $Proxy0)是 JVM 在运行时动态生成的,没有源码、没有 public 构造器,也不在类路径下。试图用反射加载它会失败:
-
Class.forName("$Proxy0")找不到类 - 即使拿到 Class,
getDeclaredConstructor().newInstance()会抛NoSuchMethodException或InstantiationException - Proxy 类本身是抽象的,不能 new,也不能被继承
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











