• JDK动态代理的实现原理


    JDK动态代理的实现原理

    1、示例demo

    • 计算接口
    package com.zcqby.proxy.jdk;
    
    public interface Calculator {
    
        public int add(int i, int j);
    
        public int sub(int i, int j);
    
        public int mult(int i, int j);
    
        public int div(int i, int j);
    }
    
    • 实现类
    package com.zcqby.proxy.jdk;
    
    public class MyCalculator implements Calculator {
        @Override
        public int add(int i, int j) {
            int result = i + j;
            return result;
        }
    
        @Override
        public int sub(int i, int j) {
            int result = i - j;
            return result;
        }
    
        @Override
        public int mult(int i, int j) {
            int result = i * j;
            return result;
        }
    
        @Override
        public int div(int i, int j) {
            int result = i / j;
            return result;
        }
    }
    
    • 代理类
    package com.zcqby.proxy.jdk;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class CalculatorProxy {
        public static Calculator getProxy(final Calculator calculator){
            ClassLoader loader = calculator.getClass().getClassLoader();
            Class<?>[] interfaces = calculator.getClass().getInterfaces();
            InvocationHandler h = new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    Object result = null;
                    try {
                        result = method.invoke(calculator, args);
                    } catch (Exception e) {
                    } finally {
                    }
                    return result;
                }
            };
            Object proxy = Proxy.newProxyInstance(loader, interfaces, h);
            return (Calculator) proxy;
        }
    }
    
    • 测试类
    package com.zcqby.proxy.jdk;
    
    public class Test {
        public static void main(String[] args) {
            System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
            Calculator proxy = CalculatorProxy.getProxy(new MyCalculator());
            proxy.add(1,1);
            proxy.div(10,100);
            System.out.println(proxy.getClass());
        }
    }
    

    2、源码跟踪

    image-20220705193836042

    image-20220705194018318

    image-20220705194142592

    • 上图的注释部分, 我们可以大致知道, 就是 如果proxyClassCache 缓存中已经有了这个对象,那么我们就直接从缓存中获取对象;
    • 如果缓存中没有该对象, 则我们就需要通过 ProxyClassFactory 代理类工厂去创建对象。

    image-20220705194622139

    image-20220705194840236

    • 值得注意的是, 这边的 map 的数据结构是 是 map里面套map,并且使用的 ConcurrentMap

    image-20220705200509984

    如上图所示, 动态代理的class文件生成的主要实现, 就是上图所示的ProxyClassFactory 中,这里就是真实的创建动态代理生成的class文件的地方。

    image-20220705201122292

    image-20220705201505461

    image-20220705201650758

    image-20220705201823131

    image-20220705203428327

    image-20220705203651872

    image-20220705204120279

    image-20220705204213711

    image-20220705204537011

    image-20220705204847326

    image-20220705205723261

    image-20220705210011729

    image-20220705210128828

    image-20220705210411402

    image-20220705210803756

    image-20220705210914209

    image-20220705211047427

    image-20220705211256195

    执行完上述逻辑后, 不断返回个上层调用者, 最终到如下图的位置的时候, 就有了代理类

    image-20220705211457302

    image-20220705211554327

    image-20220705211804746

    image-20220705212156706

    image-20220705212559992

  • 相关阅读:
    SpringBoot-14-MyBatis预热篇,MySQL小结
    SpringBoot-13-插曲之Node文件重命名+自动生成json对象
    八月十九风雨大作
    诉世书
    《仪式》
    珊瑚墓地
    新生
    《应龙》
    《枝·你是树的狂舞》
    golang中使用etcd
  • 原文地址:https://www.cnblogs.com/qianzhengkai/p/16448734.html
Copyright © 2020-2023  润新知