java动态代理(动态代理)

 2025-08-26 01:42:01  阅读 1014  评论 0

摘要:代理模式理解:不直接访问目标类,通过代理类调用目标类来完成操作。简而言之就是直接调用变为了间接调用。好处:在代理类调用目标类之前和之后去添加一些预处理和后处理的操作,扩展不属于目标类的功能。代理分类静态代理:需要我们事先编写目标类对应的代理类代码,然后编译

动态代理-JDK你还不懂吗?

代理模式

理解:不直接访问目标类,通过代理类调用目标类来完成操作。

简而言之就是直接调用变为了间接调用。

好处:在代理类调用目标类之前和之后去添加一些预处理和后处理的操作,扩展不属于目标类的功能。

代理分类

静态代理:需要我们事先编写目标类对应的代理类代码,然后编译生成字节码文件。

在程序运行时直接去读这些字节码文件进行运行。

动态代理:不需要事先给目标类编写代理类代码,而是在运行中通过反射自动生成代理对象(以JDK动态代理举例)。

动态代理

JDK

JDK动态代理是基于Java的反射机制实现的。使用jdk中接口和类实现代理对象的动态创建。

JDK的动态要求目标对象必须实现接口,这是java设计上的要求。

从jdk1.3以来, java语言通过java.lang.reflect包提供三个类支持代理模式Proxy, Method和 InovcationHandler.

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;

public class TestReflect {
    public static void main(String[] args) {
        //System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
        ProxyHandler proxyHandler = new ProxyHandler();
        List list = (List)proxyHandler.getInstance(new ArrayList());
        list.add("这里代理的是ArrayList类");
    }
}

//实现InvocationHandler的Handler
class ProxyHandler implements InvocationHandler{

    private  Object targetObj;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("执行前");
        Object invoke = method.invoke(targetObj, args);
        System.out.println("执行后");
        return invoke;
    }

    public  Object getInstance(Object targetObj){
        this.targetObj=targetObj;
        //创建一个代理类,参数固定: 目标对象类加载器,目标对象接口,实现了InvocationHandler的Handler
        return Proxy.newProxyInstance(
                targetObj.getClass().getClassLoader(),
                targetObj.getClass().getInterfaces(),
                this
        );
    }
}

由于ArrayList实现了List接口,我们直接拿ArrayList进行测试。

demo中并没有事先编写ArrayList的代理类,为什么能够代理ArrayList类呢?

Proxy类中的newProxyInstance会调用getProxyClass0方法getProxyClass0会从proxyClassCache中获取ClassproxyClassCache构建的第二个参数 ProxyClassFactory()中apply()方法会生成字节码ProxyGenerator.generateProxyClass()会根据saveGeneratedFiles这个boolean值判断是否在本地生成字节码文件我们在测试代码中加入System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles","true")这句话就会在本地生成代理类的字节码文件。
    public static Object newProxyInstance(ClassLoader loader,
                                          Class[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {   /*
         * Look up or generate the designated proxy class.
         */
        Class cl = getProxyClass0(loader, intfs);
        //忽略其他代码

    private static Class getProxyClass0(ClassLoader loader,
                                           Class... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
        return proxyClassCache.get(loader, interfaces);
    }

    private static final WeakCache[], Class>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

    private static final class ProxyClassFactory
        implements BiFunction[], Class>
    {
        // 忽略其他代码

        @Override
        public Class apply(ClassLoader loader, Class[] interfaces) {
        /*
             * Generate the specified proxy class.
             */
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);

private static final boolean saveGeneratedFiles = (Boolean)AccessController.doPrivileged(new GetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles"));

public static byte[] generateProxyClass(final String var0, Class[] var1, int var2) {
        ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
        final byte[] var4 = var3.generateClassFile();
        if (saveGeneratedFiles) {
            // 忽略其他代码
        }
}

动态代理-JDK你还不懂吗?

动态代理-JDK你还不懂吗?

从图中可以看出,代理类对象实现了ArrayList类中实现的所有接口,并且继承了一个Proxy类。

Proxy类中有定义InvocationHandler 成员属性,

protected InvocationHandler h;

又因为代理类中有目标类中的所有方法,即可通过调用Proxy类的InvocationHandler的实现类的invoke方法来完成对目标类的代理。

jdk动态代理的缺陷:

Java是单继承机制,目标类如果继承了一些父类的方法,那么代理类就无法操作那些方法;(因为代理类必须继承Proxy类,那就无法继承目标类的父类了)目标类没有接口就无法实现动态代理,显然不合理。

版权声明:我们致力于保护作者版权,注重分享,被刊用文章【java动态代理(动态代理)】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!;

原文链接:https://www.yxiso.com/zhishi/2106136.html

标签:java动态代理

发表评论:

关于我们
院校搜的目标不仅是为用户提供数据和信息,更是成为每一位学子梦想实现的桥梁。我们相信,通过准确的信息与专业的指导,每一位学子都能找到属于自己的教育之路,迈向成功的未来。助力每一个梦想,实现更美好的未来!
联系方式
电话:
地址:广东省中山市
Email:beimuxi@protonmail.com

Copyright © 2022 院校搜 Inc. 保留所有权利。 Powered by BEIMUCMS 3.0.3

页面耗时0.0378秒, 内存占用1.93 MB, 访问数据库24次

陕ICP备14005772号-15