跨境派

跨境派

跨境派,专注跨境行业新闻资讯、跨境电商知识分享!

当前位置:首页 > 工具系统 > 监控软件 > Java 动态代理Proxy应用和底层源码分析

Java 动态代理Proxy应用和底层源码分析

时间:2024-04-15 15:50:25 来源:网络cs 作者:晨起 栏目:监控软件 阅读:

标签: 分析  动态  代理 

文章目录

前言一、Proxy代码示例二、底层源码分析


前言

Java Proxy主要用于创建动态代理实例,这些实例实现了指定的一组接口,并在调用方法时将调用转发给指定的调用处理器(InvocationHandler)。这种机制常用于实现AOP(面向切面编程)框架、RPC(远程过程调用)框架等,以及任何需要动态改变对象行为的场景。


一、Proxy代码示例

在这个示例中,我们创建了一个实现了 MyInterface 接口的匿名内部类对象 myObject。然后,我们创建了一个 MyInvocationHandler 对象,并将 myObject 作为目标对象传递给它。接下来,我们使用 Proxy.newProxyInstance 方法创建了一个代理对象 proxy,并将 MyInterface 接口和 handler 作为参数传递给它。最后,我们调用代理对象的 doSomething 方法,这个方法调用会转发给 handler 的 invoke 方法,并在其中添加自定义逻辑。

interface MyInterface {    void doSomething();}class MyInvocationHandler implements InvocationHandler {    private Object target;    public MyInvocationHandler(Object target) {        this.target = target;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("Before method call");        Object result = method.invoke(target, args);        System.out.println("After method call");        return result;    }}public class DynamicProxyExample {    public static void main(String[] args) {        MyInterface myObject = new MyInterface() {            @Override            public void doSomething() {                System.out.println("Doing something");            }        };        MyInvocationHandler handler = new MyInvocationHandler(myObject);        MyInterface proxy = (MyInterface) Proxy.newProxyInstance(                MyInterface.class.getClassLoader(),                new Class<?>[]{MyInterface.class},                handler        );        proxy.doSomething(); // This will call the proxy's doSomething method, which forwards to the handler's invoke method.    }}

二、底层源码分析

从newProxyInstance这个入口来看看Proxy的重点方法。
public static Object newProxyInstance(ClassLoader loader,                                          Class<?>[] interfaces,                                          InvocationHandler h) throws IllegalArgumentException {        //将接口clone,之后对此clone类进行操作        final Class<?>[] intfs = interfaces.clone();        //进行权限检查        final SecurityManager sm = System.getSecurityManager();        if (sm != null) {            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);        }        /*         * Look up or generate the designated proxy class.         * 根据传入的类加载器和接口类数组,生成相应的代理类         */        Class<?> cl = getProxyClass0(loader, intfs);        /*         * Invoke its constructor with the designated invocation handler.         */        try {            if (sm != null) {                checkNewProxyPermission(Reflection.getCallerClass(), cl);            }            //获取构造            final Constructor<?> cons = cl.getConstructor(constructorParams);            final InvocationHandler ih = h;            if (!Modifier.isPublic(cl.getModifiers())) {                AccessController.doexposingd(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);        }     }
再来看查找/生成的代理类getProxyClass0
    /**     * Generate a proxy class.  Must call the checkProxyAccess method     * to perform permission checks before calling this.     */    private static Class<?> getProxyClass0(ClassLoader loader,                                           Class<?>... interfaces) {        if (interfaces.length > 65535) {            throw new IllegalArgumentException("interface limit exceeded");        }        // 如果由实现给定接口的给定加载器定义的代理类存在,将返回缓存的副本;        // 否则,它将通过ProxyClassFactory创建代理类        return proxyClassCache.get(loader, interfaces);    }
/**     * a cache of proxy classes     * 动态代理类的弱缓存容器     * KeyFactory:根据接口的数量,映射一个最佳的key生成函数,其中表示接口的类对象被弱引用;     * 也就是key对象被弱引用继承自WeakReference(key0、key1、key2、keyX),  保存接口密钥(hash值)     * ProxyClassFactory:生成动态类的工厂     */    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
WeakCache.get(loader, interfaces)
  // key 表示缓存键,parameter 表示参数。它的返回值类型为 V,表示缓存值。  public V get(K key, P parameter) {        // 判断parameter不能为空        Objects.requireNonNull(parameter);        expungeStaleEntries();        Object cacheKey = CacheKey.valueOf(key, refQueue);        // 该方法将 key 和 refQueue 作为参数调用 CacheKey.valueOf() 方法,生成一个缓存键 cacheKey,并从缓存中获取与该缓存键相关的 valuesMap。        // 如果 valuesMap 不存在,则创建一个新的 ConcurrentHashMap 对象,并将其加入到缓存中。valuesMap 是一个 ConcurrentMap 对象,它用于存储缓存键下的子键和值的提供者,其中子键由 subKeyFactory 参数生成。        ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);        if (valuesMap == null) {            ConcurrentMap<Object, Supplier<V>> oldValuesMap                = map.putIfAbsent(cacheKey,                                  valuesMap = new ConcurrentHashMap<>());            if (oldValuesMap != null) {                valuesMap = oldValuesMap;            }        }        // 利用Key的工厂类根据key和parameter参数生成键        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));        // 根据该键获取到Supplier对象,表示结果的提供者。Supplier接口包含了一个get方法        Supplier<V> supplier = valuesMap.get(subKey);        Factory factory = null;        while (true) {            if (supplier != null) {                // supplier可能是一个工厂类实例,或者是一个CacheValue<V>实例                V value = supplier.get();                if (value != null) {                    return value;                }            }            if (factory == null) {                // 核心的创建代理类的原理在Factory类里实现                // Factory类实际上也是Supplier接口的实现类,实现了get方法                factory = new Factory(key, parameter, subKey, valuesMap);            }            if (supplier == null) {                supplier = valuesMap.putIfAbsent(subKey, factory);                if (supplier == null) {                    // 将上面的Factory类对象赋值给suppler,在下一次循环时,就可以调用Factory类的get方法来生成代理类                    supplier = factory;                }            } else {                if (valuesMap.replace(subKey, supplier, factory)) {                    supplier = factory;                } else {                    // retry with current supplier                    supplier = valuesMap.get(subKey);                }            }        }    }

代码核心逻辑:
factory = new Factory(key, parameter, subKey, valuesMap);:// 创建Factory对象,Factory类是Supplier接口的实现类
supplier = factory; // 当缓存中不存在代理类时,将supplier=factory对象
V value = supplier.get(); // 调用Factory类的get方法来创建代理类

Factory.get()
        public synchronized V get() {                           V value = null;            try {                //valueFactory实际上是一个ProxyClassFactory实例,调用的是ProxyClassFactory.apply方法                value = Objects.requireNonNull(valueFactory.apply(key, parameter));            } finally {                if (value == null) {                     valuesMap.remove(subKey, this);                }            }            // wrap value with CacheValue (WeakReference)            CacheValue<V> cacheValue = new CacheValue<>(value);            // put into reverseMap            reverseMap.put(cacheValue, Boolean.TRUE);            // try replacing us with CacheValue (this should always succeed)            if (!valuesMap.replace(subKey, this, cacheValue)) {                throw new AssertionError("Should not reach here");            }            return value;        }    }
ProxyClassFactory.apply
ProxyClassFactory是Proxy的静态内部类,apply 用于生成代理类的Class对象
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);            for (Class<?> intf : interfaces) {                /*                 * Verify that the class loader resolves the name of this interface to the same Class object.                 */                Class<?> interfaceClass = null;                try {                    interfaceClass = Class.forName(intf.getName(), false, loader);                } catch (ClassNotFoundException e) {                }                /*                 * Verify that the Class object actually represents an interface.                 */                if (!interfaceClass.isInterface()) {                    throw new IllegalArgumentException(                        interfaceClass.getName() + " is not an interface");                }            }            String proxyPkg = null;     // package to define proxy class in            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;            /*             * Record the package of a non-public proxy interface so that the             * proxy class will be defined in the same package.  Verify that             * all non-public proxy interfaces are in the same package.             */            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) {                // if no non-public proxy interfaces, use com.sun.proxy package                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";            }            /*             * Choose a name for the proxy class to generate.             */            long num = nextUniqueNumber.getAndIncrement();            String proxyName = proxyPkg + proxyClassNamePrefix + num;            /*             * Generate the specified proxy class.             */            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(                proxyName, interfaces, accessFlags);            return defineClass0(loader, proxyName,                                    proxyClassFile, 0, proxyClassFile.length);    }
ProxyGenerator.generateProxyClass
generateProxyClass 生成代理类字节码
    private byte[] generateClassFile() {        //生成hashCode方法        this.addProxyMethod(hashCodeMethod, Object.class);        //生成equals方法        this.addProxyMethod(equalsMethod, Object.class);        //生成toString方法        this.addProxyMethod(toStringMethod, Object.class);        Class[] var1 = this.interfaces;        int var2 = var1.length;        int var3;        Class var4;        for(var3 = 0; var3 < var2; ++var3) {            var4 = var1[var3];            Method[] var5 = var4.getMethods();            int var6 = var5.length;            for(int var7 = 0; var7 < var6; ++var7) {                Method var8 = var5[var7];                this.addProxyMethod(var8, var4);            }        }        Iterator var11 = this.proxyMethods.values().iterator();        List var12;        while(var11.hasNext()) {            var12 = (List)var11.next();            checkReturnTypes(var12);        }        Iterator var15;        try {            this.methods.add(this.generateConstructor());            var11 = this.proxyMethods.values().iterator();            while(var11.hasNext()) {                var12 = (List)var11.next();                var15 = var12.iterator();                while(var15.hasNext()) {                    ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next();                    this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10));                    this.methods.add(var16.generateMethod());                }            }            this.methods.add(this.generateStaticInitializer());        } catch (IOException var10) {            throw new InternalError("unexpected I/O Exception", var10);        }        if (this.methods.size() > 65535) {            throw new IllegalArgumentException("method limit exceeded");        } else if (this.fields.size() > 65535) {            throw new IllegalArgumentException("field limit exceeded");        } else {            this.cp.getClass(dotToSlash(this.className));            this.cp.getClass("java/lang/reflect/Proxy");            var1 = this.interfaces;            var2 = var1.length;            for(var3 = 0; var3 < var2; ++var3) {                var4 = var1[var3];                this.cp.getClass(dotToSlash(var4.getName()));            }            this.cp.setReadOnly();            ByteArrayOutputStream var13 = new ByteArrayOutputStream();            DataOutputStream var14 = new DataOutputStream(var13);            try {                var14.writeInt(-889275714);                var14.writeShort(0);                var14.writeShort(49);                this.cp.write(var14);                var14.writeShort(this.accessFlags);                var14.writeShort(this.cp.getClass(dotToSlash(this.className)));                var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy"));                var14.writeShort(this.interfaces.length);                Class[] var17 = this.interfaces;                int var18 = var17.length;                for(int var19 = 0; var19 < var18; ++var19) {                    Class var22 = var17[var19];                    var14.writeShort(this.cp.getClass(dotToSlash(var22.getName())));                }                var14.writeShort(this.fields.size());                var15 = this.fields.iterator();                while(var15.hasNext()) {                    ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next();                    var20.write(var14);                }                var14.writeShort(this.methods.size());                var15 = this.methods.iterator();                while(var15.hasNext()) {                    ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next();                    var21.write(var14);                }                var14.writeShort(0);                return var13.toByteArray();            } catch (IOException var9) {                throw new InternalError("unexpected I/O Exception", var9);            }        }    }

本文链接:https://www.kjpai.cn/news/2024-04-15/159040.html,文章来源:网络cs,作者:晨起,版权归作者所有,如需转载请注明来源和作者,否则将追究法律责任!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。

文章评论