JDK动态代理源码梳理文档
一、整体源码调用链路
Proxy.newProxyInstance() → getProxyConstructor() → proxyCache.computeIfAbsent() → Memoizer.get() → ProxyBuilder.build() → cons.newInstance(h)
1、入口方法 newProxyInstance
java
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h) {
Objects.requireNonNull(h);
@SuppressWarnings("removal")
final Class<?> caller = System.getSecurityManager() == null
? null
: Reflection.getCallerClass();
Constructor<?> cons = getProxyConstructor(caller, loader, interfaces);
return newProxyInstance(caller, cons, h);
}
@CallerSensitive:JVM标识,允许native方法Reflection.getCallerClass()读取调用栈获取调用类;caller赋值逻辑:无安全管理器(默认环境) → caller = null,跳过全部权限校验;开启安全管理器才获取调用方Class做权限校验;- 99.9%业务环境
caller=null,直接放行代理类生成。
2、getProxyConstructor(缓存分支分发)
区分单个接口/多个接口两条分支,逻辑一致:
caller != null:执行checkProxyAccess权限校验;caller = null:跳过权限校验,进入缓存逻辑;- 依托
proxyCache做代理类缓存,computeIfAbsent实现「有缓存直接取构造器,无缓存则构建ProxyBuilder生成代理类」。
3、computeIfAbsent(高并发缓存自旋逻辑)
- 依托
ConcurrentHashMap做代理构造器缓存,while(true)自旋处理多线程并发创建同一个代理类竞争; Memoizer为延迟创建任务封装:缓存不存在时初始化Memoizer,putIfAbsent抢占缓存位,抢占成功执行生成逻辑;- 生成异常则移除缓存key,后续请求复用异常结果。
4、Memoizer.get()(单例生成、DCL+同步锁)
java
public V get() throws RecursiveInvocationException {
V v = this.v;
if (v != null) return v;
Throwable t = this.t;
if (t == null) {
synchronized (this) {
if ((v = this.v) == null && (t = this.t) == null) {
if (inCall) {
throw new RecursiveInvocationException();
}
inCall = true;
try {
this.v = v = Objects.requireNonNull(
mappingFunction.apply(cl, clv));
} catch (Throwable x) {
this.t = t = x;
} finally {
inCall = false;
}
}
}
}
if (v != null) return v;
// 异常分类抛出
if (t instanceof Error) throw (Error) t;
else if (t instanceof RuntimeException) throw (RuntimeException) t;
else throw new UndeclaredThrowableException(t);
}
- DCL双重检查+synchronized锁:保证同一个接口+类加载器的代理类只生成一次;
inCall标记:防止代理生成时递归调用造成死循环;- 生成结果/异常均缓存,后续线程直接复用结果或异常。
5、ProxyBuilder.build()(生成代理Class、获取构造器)
java
Constructor<?> build() {
Class<?> proxyClass = defineProxyClass(module, interfaces);
// JDK9+模块权限断言
assert !module.isNamed() || module.isOpen(proxyClass.getPackageName(), Proxy.class.getModule());
final Constructor<?> cons;
try {
cons = proxyClass.getConstructor(constructorParams);
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
// 特权放行,放开构造器访问权限
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
return cons;
}
defineProxyClass:底层拼接字节码、Unsafe加载Class,生成$ProxyN代理类;- 获取入参为
InvocationHandler的唯一构造方法,特权修改访问权限; - 返回构造器,供反射实例化。
6、实例化:cons.newInstance(new Object\[\]{h})
反射调用代理类构造方法,将自定义InvocationHandler传入,最终生成代理对象,等价代码:new $Proxy0(h)。
二、运行时生成完整代理类$Proxy0示例
java
public final class $Proxy0 extends Proxy implements UserService {
private static Method mAdd;
private static Method mDelete;
private static Method mEquals;
private static Method mToString;
private static Method mHashCode;
static {
try {
mAdd = Class.forName("UserService").getMethod("add");
mDelete = Class.forName("UserService").getMethod("delete");
mEquals = Object.class.getMethod("equals", Object.class);
mToString = Object.class.getMethod("toString");
mHashCode = Object.class.getMethod("hashCode");
} catch (Exception e) {
throw new NoClassDefFoundError(e.getMessage());
}
}
public $Proxy0(InvocationHandler var1) {
super(var1);
}
public final void add() {
try {
super.h.invoke(this, mAdd, null);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
public final void delete() {
try {
super.h.invoke(this, mDelete, null);
} catch (Throwable e) {
throw new UndeclaredThrowableException(e);
}
}
public final boolean equals(Object o) {
return (Boolean) super.h.invoke(this, mEquals, new Object[]{o});
}
public final String toString() {
return (String) super.h.invoke(this, mToString, null);
}
public final int hashCode() {
return (Integer) super.h.invoke(this, mHashCode, null);
}
}
核心:代理类无业务实现,所有接口方法+Object三大方法全部转发至
InvocationHandler.invoke()。
三、自定义InvocationHandler两大关键点
- 必须持有目标对象target引用
java
class MyHandler implements InvocationHandler {
private final Object target;
public MyHandler(Object target) { this.target = target; }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置增强
Object res = method.invoke(target, args); // 调用真实目标方法
// 后置增强
return res;
}
}
代理壳子只做转发,依靠target执行原生业务逻辑。
- 多方法差异化增强,需要在invoke内判断Method
原生硬编码弊端:大量if-else、耦合严重、不易扩展;Spring AOP通过Pointcut切点匹配、拦截器链优化该痛点,替代手动判断Method。
四、核心总结
- JDK动态代理本质:运行时动态生成实现目标接口的字节码类,所有方法转发至InvocationHandler;
- 缓存设计:JDK内置多级缓存+锁控制,避免重复生成代理类,节省JVM内存;
- 设计短板:仅支持接口代理、差异化增强需手动判断方法,催生Spring AOP封装优化。