JDK8源码分析Jdk动态代理底层原理

打印 上一主题 下一主题

主题 1818|帖子 1818|积分 5454

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
 本文侧重分析JDK8中jdk动态代理的源码,若是想看JDK17源码分析可以看我的这一篇文章 JDK17源码分析Jdk动态代理底层原理-CSDN博客
两者之间有着略微的差别,JDK17在JDK8上改进了不少
目录
源码分析 
过程
生成的代理类大致结构

 本文侧重分析JDK8中jdk动态代理的源码,若是想看JDK17源码分析可以看我的这一篇文章 JDK17源码分析Jdk动态代理底层原理-CSDN博客
两者之间有着略微的差别,JDK17在JDK8上改进了不少

      InvocationHandler最终存储在代理类实例的h字段中,这个字段是从Proxy类继承的。当调用代理对象的方法时,会调用这个h字段引用的InvocationHandler实例的invoke方法。如许就实现了方法调用的拦截和处置惩罚。 

源码分析 

  1. public class Proxy implements java.io.Serializable {
  2.     /**
  3.      * InvocationHandler对象,用于处理代理类的方法调用
  4.      * 这个字段会被所有代理类继承,存储在代理类实例中
  5.      */
  6.     protected InvocationHandler h;
  7.    
  8.     /**
  9.      * 代理类的构造函数,将InvocationHandler传递给代理类实例
  10.      * 这个构造函数会被所有代理类调用
  11.      */
  12.     protected Proxy(InvocationHandler h) {
  13.         Objects.requireNonNull(h);
  14.         this.h = h;
  15.     }
  16.     /**
  17.      * 创建代理类实例的核心方法
  18.      * loader: 类加载器,用于加载代理类
  19.      * interfaces: 代理类需要实现的接口数组
  20.      * h: 调用处理器,用于处理代理类的方法调用
  21.      */
  22.     @CallerSensitive
  23.     public static Object newProxyInstance(ClassLoader loader,
  24.                                         Class<?>[] interfaces,
  25.                                         InvocationHandler h) {
  26.         // 检查InvocationHandler是否为空
  27.         Objects.requireNonNull(h);
  28.         // 复制接口数组,确保安全性
  29.         final Class<?>[] intfs = interfaces.clone();
  30.         
  31.         // 获取安全管理器
  32.         final SecurityManager sm = System.getSecurityManager();
  33.         if (sm != null) {
  34.             // 检查权限
  35.             checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
  36.         }
  37.         /*
  38.          * 查找或生成代理类
  39.          * 这是最核心的步骤,会生成代理类的字节码
  40.          */
  41.         Class<?> cl = getProxyClass0(loader, intfs);
  42.         try {
  43.             // 检查权限
  44.             if (sm != null) {
  45.                 checkNewProxyPermission(Reflection.getCallerClass(), cl);
  46.             }
  47.             // 获取代理类的构造函数
  48.             final Constructor<?> cons = cl.getConstructor(constructorParams);
  49.             final InvocationHandler ih = h;
  50.             
  51.             // 如果构造函数是非public的,设置其可访问
  52.             if (!Modifier.isPublic(cl.getModifiers())) {
  53.                 AccessController.doPrivileged(new PrivilegedAction<Void>() {
  54.                     public Void run() {
  55.                         cons.setAccessible(true);
  56.                         return null;
  57.                     }
  58.                 });
  59.             }
  60.             
  61.             // 创建代理类实例
  62.             return cons.newInstance(new Object[]{h});
  63.             
  64.         } catch (IllegalAccessException|InstantiationException e) {
  65.             throw new InternalError(e.toString(), e);
  66.         } catch (InvocationTargetException e) {
  67.             throw new InternalError(e.toString(), e);
  68.         } catch (NoSuchMethodException e) {
  69.             throw new InternalError(e.toString(), e);
  70.         }
  71.     }
  72.     /**
  73.      * 获取代理类的核心方法
  74.      * 这个方法会调用ProxyClassFactory来生成代理类
  75.      */
  76.     private static Class<?> getProxyClass0(ClassLoader loader,
  77.                                          Class<?>[] interfaces) {
  78.         // 如果接口数量超过65535,抛出异常
  79.         if (interfaces.length > 65535) {
  80.             throw new IllegalArgumentException("interface limit exceeded");
  81.         }
  82.         // 从缓存中获取代理类,如果不存在则生成
  83.         return proxyClassCache.get(loader, interfaces);
  84.     }
  85. }
  86. /**
  87. * 代理类工厂,负责生成代理类的字节码
  88. */
  89. private static final class ProxyClassFactory
  90.     implements BiFunction<ClassLoader, Class<?>[], Class<?>> {
  91.    
  92.     // 代理类名称前缀
  93.     private static final String proxyClassNamePrefix = "$Proxy";
  94.     // 原子计数器,用于生成唯一的代理类名
  95.     private static final AtomicLong nextUniqueNumber = new AtomicLong();
  96.     @Override
  97.     public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
  98.         Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
  99.         
  100.         // 验证接口
  101.         for (Class<?> intf : interfaces) {
  102.             // 验证类加载器能否加载这个接口
  103.             validateInterface(intf, loader, interfaceSet);
  104.         }
  105.         // 生成代理类的名称
  106.         String proxyPkg = null;     // 包名
  107.         int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
  108.         // 检查所有非公共接口是否在同一个包中
  109.         for (Class<?> intf : interfaces) {
  110.             int flags = intf.getModifiers();
  111.             if (!Modifier.isPublic(flags)) {
  112.                 accessFlags = Modifier.FINAL;  // 移除public标志
  113.                 String pkg = intf.getPackageName();
  114.                 if (proxyPkg == null) {
  115.                     proxyPkg = pkg;
  116.                 } else if (!pkg.equals(proxyPkg)) {
  117.                     throw new IllegalArgumentException(
  118.                         "non-public interfaces from different packages");
  119.                 }
  120.             }
  121.         }
  122.         // 如果没有指定包名,默认使用com.sun.proxy
  123.         if (proxyPkg == null) {
  124.             proxyPkg = "com.sun.proxy";
  125.         }
  126.         // 生成代理类的完整名称
  127.         long num = nextUniqueNumber.getAndIncrement();
  128.         String proxyName = proxyPkg.isEmpty()
  129.                           ? proxyClassNamePrefix + num
  130.                           : proxyPkg + "." + proxyClassNamePrefix + num;
  131.         // 生成代理类的字节码
  132.         byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
  133.             proxyName, interfaces, accessFlags);
  134.         try {
  135.             // 加载代理类
  136.             return defineClass0(loader, proxyName,
  137.                               proxyClassFile, 0, proxyClassFile.length);
  138.         } catch (ClassFormatError e) {
  139.             throw new IllegalArgumentException(e.toString());
  140.         }
  141.     }
  142. }
复制代码
过程

JDK动态代理生成代理对象的过程可以分为以下几个关键步调:
1.调用Proxy.newProxyInstance方法,传入类加载器、接口数组和InvocationHandler实例。这是整个代理创建过程的入口。
2.通过getProxyClass0方法获取代理类。这个方法会首先查抄缓存中是否已经存在对应的代理类,如果不存在则创建新的代理类。
3.ProxyClassFactory负责生成代理类的字节码,此中会,验证接口的合法性,生成唯一的代理类名,确定代理类的包名,调用ProxyGenerator生成字节码
4. 获取代理类的构造函数,这个构造函数吸取一个InvocationHandler参数。
5.使用构造函数创建代理类实例,将InvocationHandler传入。这个InvocationHandler会被存储在代理类的h字段中。

生成的代理类大致结构

  1. public final class $Proxy0 extends Proxy implements UserService {
  2.    
  3.    
  4.     // 静态方法对象,用于方法调用
  5.     private static Method m1;
  6.     private static Method m2;
  7.     private static Method m3;
  8.    
  9.     static {
  10.         try {
  11.             // 初始化方法对象
  12.             m1 = Class.forName("java.lang.Object")
  13.                      .getMethod("equals", Object.class);
  14.             m2 = Class.forName("com.example.UserService")
  15.                      .getMethod("addUser", String.class);
  16.             // ... 其他方法
  17.         } catch (NoSuchMethodException e) {
  18.             throw new NoSuchMethodError(e.getMessage());
  19.         }
  20.     }
  21.    
  22.     // 构造函数,调用父类构造函数存储InvocationHandler
  23.     public $Proxy0(InvocationHandler h) {
  24.         super(h);
  25.     }
  26.    
  27.     // 实现接口方法
  28.     @Override
  29.     public void addUser(String name) {
  30.         try {
  31.             // 调用InvocationHandler的invoke方法
  32.             h.invoke(this, m2, new Object[]{name});
  33.         } catch (Throwable e) {
  34.             throw new UndeclaredThrowableException(e);
  35.         }
  36.     }
  37. }
复制代码
       InvocationHandler最终存储在代理类实例的h字段中,这个字段是从Proxy类继承的。当调用代理对象的方法时,会调用这个h字段引用的InvocationHandler实例的invoke方法。如许就实现了方法调用的拦截和处置惩罚。 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

道家人

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表