最新公告
  • 欢迎您光临极客文库,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入我们
  • 动态代理作为Java反射的主要应用之一,其在多种JavaEE框架中均有使用,如Spring框架中AOP的实现原理就是动态代理,面试中提到AOP也必定会问 「谈谈对动态代理的理解?」 相关问题,在此做一个梳理与总结。

    谈谈对动态代理的理解?

    动态代理作为设计模式中动态代理模式的一部分,其和静态代理构成鲜明对比。下面分别对代理模式、静态代理和动态代理技术点进行详细介绍与分析。

    代理模式

    代理模式的主要思想是创建一个代理对象来包装原始对象,任何对原始对象的调用必须通过代理对象,并由代理对象来决定是否以及何时将方法调用转到原始对象上。
    说明:关于「设计模式」的详细内容,将放在后续文章进行学习和分享。

    静态代理

    静态代理的主要特征是代理类和被代理类都是在编译期间就确定下来的,一个代理类仅能为一个接口服务,不利于程序的扩展。
    实现步骤:
    • 创建被代理类所实现的接口(包括抽象方法);
    • 创建被代理类,实现相应的接口并重写其抽象方法;
    • 创建代理类,实现被代理类所实现的接口,创建构造器并传入被代理类的对象,在重写接口的抽象方法中发起对被代理类的调用。
    示例代码:
    //1.创建代理类所实现的接口 
    interface ClothFactory {
        void productCloth();
    }

    // 2.创建被代理类,并实现相应的接口
    class NikeClothFactory implements ClothFactory {
        // 重写抽象方法
        public void productCloth() {
            System.out.println(“Nike-Nike!”);
        }
    }

    // 3.创建代理类,实现被代理类所实现的接口
    class ProxyFactory implements ClothFactory {
        ClothFactory cf;
        // 创建构造器,传入的是被代理类的对象!
        public ProxyFactory(ClothFactory cf) {
            this.cf = cf;
        }
        // 重写抽象方法,发起对被代理对象方法的调用
        public void productCloth() {
            cf.productCloth();
        }
    }

    public class TestStaticProxy {
        public static void main(String[] args) {
            //1.创建被代理类对象
            NikeClothFactory ncf = new NikeClothFactory();
            //2.创建代理类对象
            ProxyFactory pf = new ProxyFactory(ncf);
            //3.执行代理类的方法,但实际发起的是对被代理类中指定方法的调用
            pf.productCloth();
        }
    }
    在代码上看,执行的是代理类的方法,但实际是通过代理类方法发起对被代理类方法的调用。

    动态代理

    动态代理主要是为了解决静态代理中一个代理类仅能服务一个接口的问题
    动态代理的主要特征是通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建被代理类的代理对象。
    实现步骤:
    • 创建被代理类所实现的接口(包括抽象方法);
    • 创建被代理类,实现相应的接口并重写其抽象方法;
    • 创建一个实现InvocationHandler接口的代理类,重写其invoke()方法以完成代理的具体操作,同时创建blind()方法一方面完成对被代理类对象的实例化,另一方面通过Proxy的静态newProxyInstance()方法返回一个动态代理类的对象
    示例代码:
    // 1.被代理类所实现的接口
    interface Subject {
        void action();
    }

    // 2.创建被代理类,实现接口并重写接口的抽象方法
    class RealSubject implements Subject {
        @Override
        public void action() {
            System.out.println(“被代理类-被代理”);
        }
    }

    // 3.创建代理类,实现InvocationHandler接口
    class MyInvocationHandler implements InvocationHandler {
        Object obj;
        // 3.1 重写invoke方法,完成代理的具体操作
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            //method为被代理类的目标方法
            Object returnVal = method.invoke(obj, args);//调用被代理类的action方法
            return returnVal;
        }
        // 3.2 实例化被代理对象,返回一个代理类对象
        public Object blind(Object obj) {
            this.obj = obj;
            // 返回一个代理类对象
            return
            Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
        }

    }

    public class TestProxy {
        public static void main(String[] args) {
            //1.创建被代理类的对象
            RealSubject real = new RealSubject();
            //2.创建代理类的对象
            MyInvocationHandler handler = new MyInvocationHandler();
            //3.调用blind()方法,动态返回一个同样实现被代理类所实现接口的代理类的对象
            Object obj = handler.blind(real);
            Subject sub = (Subject)obj;//此时的sub即为代理类的对象
            sub.action();

            NikeClothFactory ncf = new NikeClothFactory();
            obj = handler.blind(ncf);
            ClothFactory cf = (ClothFactory)obj; //此时的cf即为代理类的对象
            cf.productCloth();
        }
    }

    扩展面试题

    问:你在项目中的哪些场景下使用过动态代理?
    答:动态代理最主要的应用场景就是面向切面编程,主要在调用目标方法的前后插入一些通用处理,比如日志操作和事务处理等,示意图如下:
    动态代理应用示意图
    扩展:动态代理之Proxy类
    Proxy类是专门完成代理的操作类,其是所有动态代理类的父类,通过此类为一个或多个接口动态地生成实现类。其提供的主要静态方法如下:
    // 获取动态代理类所对应的Class对象
    static Class<?> getProxyClass(ClassLoader loader, Class<?>… interfaces)  

    // 创建动态代理对象
    static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
    本站所有文章均由网友分享,仅用于参考学习用,请勿直接转载,如有侵权,请联系网站客服删除相关文章。若由于商用引起版权纠纷,一切责任均由使用者承担
    极客文库 » 反射与动态代理

    常见问题FAQ

    如果资源链接失效了怎么办?
    本站用户分享的所有资源都有自动备份机制,如果资源链接失效,请联系本站客服QQ:2580505920更新资源地址。
    如果用户分享的资源与描述不符怎么办?
    可以联系客服QQ:2580505920,如果要求合理可以安排退款或者退赞助积分。
    如何分享个人资源获取赞助积分或其他奖励?
    本站用户可以分享自己的资源,但是必须保证资源没有侵权行为。点击个人中心,根据操作填写并上传即可。资源所获收益完全归属上传者,每周可申请提现一次。
    如果您发现了本资源有侵权行为怎么办?
    及时联系客服QQ:2580505920,核实予以删除。

    Leave a Reply

    Hi, 如果你对这款资源有疑问,可以跟我联系哦!

    联系发布者

    Leave a Reply

    Hi, 如果你对这款资源有疑问,可以跟我联系哦!

    联系发布者
    • 101会员总数(位)
    • 3672资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 128稳定运行(天)

    欢迎加入「极客文库」,成为原创作者从这里开始!

    立即加入 了解更多
    成为赞助用户享有更多特权立即升级