Java动态代理实现原理与源码分析
静态代理与动态代理对比
静态代理在编译时就生成完整的字节码和class文件,而动态代理则在运行时动态创建代理类。
静态代理实现
public interface Task {
void execute();
}
public class RealTask implements Task {
@Override
public void execute() {
System.out.println("Executing real task...");
}
}
public class TaskStaticProxy implements Task {
private final Task realTask;
public TaskStaticProxy(Task realTask) {
this.realTask = realTask;
}
@Override
public void execute() {
System.out.println("Static Proxy: Before execution");
realTask.execute();
System.out.println("Static Proxy: After execution");
}
}
静态代理的缺陷在于每个目标类都需要创建一个对应的代理类,导致代码冗余和维护困难。
JDK动态代理实现
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public interface Task {
void execute();
}
public class RealTask implements Task {
@Override
public void execute() {
System.out.println("Executing real task...");
}
}
public class TaskInvocationHandler implements InvocationHandler {
private final Object target;
public TaskInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Dynamic Proxy: Before execution");
Object result = method.invoke(target, args);
System.out.println("Dynamic Proxy: After execution");
return result;
}
}
public class DynamicProxyExample {
public static void main(String[] args) {
Task realTask = new RealTask();
Task proxy = (Task) Proxy.newProxyInstance(
realTask.getClass().getClassLoader(),
realTask.getClass().getInterfaces(),
new TaskInvocationHandler(realTask)
);
proxy.execute();
}
}
Proxy.newProxyInstance() 源码解析
核心方法 Proxy.newProxyInstance() 的签名如下:
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException {
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
Class<?> cl = getProxyClass0(loader, intfs);
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
该方法通过 getProxyClass0() 获取或生成代理类,然后通过反射调用其构造函数创建实例。
getProxyClass0() 和 ProxyClassFactory
getProxyClass0() 方法负责获取或创建代理类:
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
return proxyClassCache.get(loader, interfaces);
}
ProxyClassFactory 是生成代理类的核心工厂类,它实现了 BiFunction 接口:
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>> {
private static final String proxyClassNamePrefix = "$Proxy";
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader: " + loader);
}
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
String proxyPkg = null;
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
}
字节码生成原理
在 ProxyGenerator.generateProxyClass() 方法内部,会生成代理类的字节码。关键部分是通过 InvocationHandler.invoke() 实现方法调用:
// 获取 InvocationHandler 字段
out.writeByte(opc_getfield);
out.writeShort(cp.getFieldRef(
superclassName,
handlerFieldName, "Ljava/lang/reflect/InvocationHandler;"));
// 加载 Method 对象
code_aload(0, out);
out.writeByte(opc_getstatic);
out.writeShort(cp.getFieldRef(
dotToSlash(className),
methodFieldName, "Ljava/lang/reflect/Method;"));
// 调用 InvocationHandler.invoke 方法
out.writeByte(opc_invokeinterface);
out.writeShort(cp.getInterfaceMethodRef(
"java/lang/reflect/InvocationHandler",
"invoke",
"(Ljava/lang/Object;Ljava/lang/reflect/Method;" +
"[Ljava/lang/Object;)Ljava/lang/Object;"));
out.writeByte(4);
out.writeByte(0);
这就揭示了 JDK 动态代理的本质:生成的代理类继承 Proxy 类并持有 InvocationHandler 引用,所有方法调用都委托给 invoke() 方法处理。
动态代理在 Spring AOP 中的应用
Spring AOP 默认使用 JDK 动态代理(当目标类实现接口时)或 CGLIB 代理(当目标类未实现接口时)。动态代理是 AOP 实现方法拦截的核心机制,可以在不修改原有业务代码的情况下添加横切关注点,如日志、事务、权限控制等。