本文侧重分析JDK8中jdk动态代理的源码,若是想看JDK17源码分析可以看我的这一篇文章 JDK17源码分析Jdk动态代理底层原理-CSDN博客
两者之间有着略微的差别,JDK17在JDK8上改进了不少
目录
源码分析
过程
生成的代理类大致结构
本文侧重分析JDK8中jdk动态代理的源码,若是想看JDK17源码分析可以看我的这一篇文章 JDK17源码分析Jdk动态代理底层原理-CSDN博客
两者之间有着略微的差别,JDK17在JDK8上改进了不少
InvocationHandler最终存储在代理类实例的h字段中,这个字段是从Proxy类继承的。当调用代理对象的方法时,会调用这个h字段引用的InvocationHandler实例的invoke方法。这样就实现了方法调用的拦截和处理。
源码分析
public class Proxy implements java.io.Serializable {/** * InvocationHandler对象,用于处理代理类的方法调用* 这个字段会被所有代理类继承,存储在代理类实例中*/protected InvocationHandler h;/*** 代理类的构造函数,将InvocationHandler传递给代理类实例* 这个构造函数会被所有代理类调用*/protected Proxy(InvocationHandler h) {Objects.requireNonNull(h);this.h = h;}/*** 创建代理类实例的核心方法* loader: 类加载器,用于加载代理类* interfaces: 代理类需要实现的接口数组* h: 调用处理器,用于处理代理类的方法调用*/@CallerSensitivepublic static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) {// 检查InvocationHandler是否为空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;// 如果构造函数是非public的,设置其可访问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) {throw new InternalError(e.toString(), e);} catch (NoSuchMethodException e) {throw new InternalError(e.toString(), e);}}/*** 获取代理类的核心方法* 这个方法会调用ProxyClassFactory来生成代理类*/private static Class<?> getProxyClass0(ClassLoader loader,Class<?>[] interfaces) {// 如果接口数量超过65535,抛出异常if (interfaces.length > 65535) {throw new IllegalArgumentException("interface limit exceeded");}// 从缓存中获取代理类,如果不存在则生成return proxyClassCache.get(loader, interfaces);}
}/*** 代理类工厂,负责生成代理类的字节码*/
private static final class ProxyClassFactoryimplements BiFunction<ClassLoader, Class<?>[], Class<?>> {// 代理类名称前缀private static final String proxyClassNamePrefix = "$Proxy";// 原子计数器,用于生成唯一的代理类名private static final AtomicLong nextUniqueNumber = new AtomicLong();@Overridepublic Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);// 验证接口for (Class<?> intf : interfaces) {// 验证类加载器能否加载这个接口validateInterface(intf, loader, interfaceSet);}// 生成代理类的名称String proxyPkg = null; // 包名int accessFlags = Modifier.PUBLIC | Modifier.FINAL;// 检查所有非公共接口是否在同一个包中for (Class<?> intf : interfaces) {int flags = intf.getModifiers();if (!Modifier.isPublic(flags)) {accessFlags = Modifier.FINAL; // 移除public标志String pkg = intf.getPackageName();if (proxyPkg == null) {proxyPkg = pkg;} else if (!pkg.equals(proxyPkg)) {throw new IllegalArgumentException("non-public interfaces from different packages");}}}// 如果没有指定包名,默认使用com.sun.proxyif (proxyPkg == null) {proxyPkg = "com.sun.proxy";}// 生成代理类的完整名称long num = nextUniqueNumber.getAndIncrement();String proxyName = proxyPkg.isEmpty()? proxyClassNamePrefix + num: 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());}}
}
过程
JDK动态代理生成代理对象的过程可以分为以下几个关键步骤:
1.调用Proxy.newProxyInstance方法,传入类加载器、接口数组和InvocationHandler实例。这是整个代理创建过程的入口。
2.通过getProxyClass0方法获取代理类。这个方法会首先检查缓存中是否已经存在对应的代理类,如果不存在则创建新的代理类。
3.ProxyClassFactory负责生成代理类的字节码,其中会,验证接口的合法性,生成唯一的代理类名,确定代理类的包名,调用ProxyGenerator生成字节码
4. 获取代理类的构造函数,这个构造函数接收一个InvocationHandler参数。
5.使用构造函数创建代理类实例,将InvocationHandler传入。这个InvocationHandler会被存储在代理类的h字段中。
生成的代理类大致结构
public final class $Proxy0 extends Proxy implements UserService {// 静态方法对象,用于方法调用private static Method m1;private static Method m2;private static Method m3;static {try {// 初始化方法对象m1 = Class.forName("java.lang.Object").getMethod("equals", Object.class);m2 = Class.forName("com.example.UserService").getMethod("addUser", String.class);// ... 其他方法} catch (NoSuchMethodException e) {throw new NoSuchMethodError(e.getMessage());}}// 构造函数,调用父类构造函数存储InvocationHandlerpublic $Proxy0(InvocationHandler h) {super(h);}// 实现接口方法@Overridepublic void addUser(String name) {try {// 调用InvocationHandler的invoke方法h.invoke(this, m2, new Object[]{name});} catch (Throwable e) {throw new UndeclaredThrowableException(e);}}
}
InvocationHandler最终存储在代理类实例的h字段中,这个字段是从Proxy类继承的。当调用代理对象的方法时,会调用这个h字段引用的InvocationHandler实例的invoke方法。这样就实现了方法调用的拦截和处理。