JDK 动态代理生成的代理对象的源码
假设我们有一个 HelloService
接口和它的实现类 HelloServiceImpl
:
public interface HelloService {
void sayHello();
}
public class HelloServiceImpl implements HelloService {
@Override
public void sayHello() {
System.out.println("Hello from HelloServiceImpl!");
}
}
然后我们使用 JDK 动态代理创建 HelloService
的代理对象:
InvocationHandler handler = (proxy, method, args) -> {
System.out.println("Before method invocation");
method.invoke(new HelloServiceImpl(), args);
System.out.println("After method invocation");
return null;
};
HelloService proxy = (HelloService) Proxy.newProxyInstance(
HelloService.class.getClassLoader(),
new Class[]{HelloService.class},
handler
);
proxy.sayHello();
我们可以使用反编译工具查看 JDK 动态生成的代理对象的源码:
public final class $Proxy0 extends Proxy implements HelloService {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return ((Boolean)this.h.invoke(this, m1, new Object[]{var1})).booleanValue();
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void sayHello() throws {
try {
this.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() throws {
try {
return (String)this.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return ((Integer)this.h.invoke(this, m0, (Object[])null)).intValue();
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
m3 = Class.forName("com.example.HelloService").getMethod("sayHello", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
从生成的代理类源码可以看出:
- 代理类名为
$Proxy0
,继承了Proxy
类并实现了HelloService
接口。- 代理类持有一个
InvocationHandler
实例h
,所有方法调用最终会委托给这个InvocationHandler
。- 代理类重写了
equals()
、toString()
、hashCode()
等Object
类的方法。- 代理类重写了
HelloService
接口中的sayHello()
方法。- 代理类在静态初始化块中缓存了一些方法引用,用于提高方法调用的性能。
总之,JDK 动态代理生成的代理类是一个实现了目标接口的 Proxy 子类,它将所有方法调用委托给了 InvocationHandler
实现类,从而实现了动态代理的功能。
注意
- 限制:代理增强是借助多态来实现,因此成员变量、静态方法、final 方法均不能通过代理实现
- 前 16 次反射性能较低
public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { Class<?> caller = Reflection.getCallerClass(); checkAccess(caller, clazz, obj, modifiers); } return invoke0(obj, args); } private native Object invoke0(Object obj, Object[] args) throws IllegalArgumentException, InvocationTargetException { // JVM 调用逻辑 }
- 第 17 次调用会生成代理类,invoke() 方法优化为非反射调用