zoukankan      html  css  js  c++  java
  • 学习动态代理设计模式

    原文发在了我的github page 上 可以点击跳转[http://www.sogeisetsugo.tk/myBlog/代理设计模式]# 学习代理设计模式
    转载请注明来源

    proxy

    A dynamic proxy class (simply referred to as a proxy class below) is a class that implements a list of interfaces specified at runtime when the class is created, with behavior as described below. A proxy interface is such an interface that is implemented by a proxy class. A proxy instance is an instance of a proxy class. Each proxy instance has an associated invocation handler object, which implements the interface InvocationHandler. A method invocation on a proxy instance through one of its proxy interfaces will be dispatched to the invoke method of the instance's invocation handler, passing the proxy instance, a java.lang.reflect.Method object identifying the method that was invoked, and an array of type Object containing the arguments. The invocation handler processes the encoded method invocation as appropriate and the result that it returns will be returned as the result of the method invocation on the proxy instance.

    翻译(本人人工翻译,在个人理解的基础上稍有修改,请重点看加粗的内容,并绕过这些非加粗的内容,非加粗的内容是对翻译内容的注释)

    proxy类是什么?是一个在创建(即实例化)后在运行时会实现很多特殊接口的类

    proxy类的表现?先明确一个概念: 代理接口指的是被proxy类实现的接口。代理实例指的是proxy类的实例化对象 。每一个代理实例都会关联(所谓关联,即和什么东西有关系。比如和狗有关联,即和狗有某关系,仅此而已)一个被称作invocation handler object(译作调用帮手?)的object。这个object实现了一个叫InvocationHandler的接口。一个代理实例的方法调用通过代理接口被发送到invocation handler object的调用方法( the invoke method),通过代理实例, a java.lang.reflect.Method object找到被调用的方法( the invoke method)和包含数据的数组。返回的结果将作为代理实例上方法调用的结果返回

    InvocationHandler

    InvocationHandler是一个接口,通过实现这个接口变成invocation handler object。有一个方法叫invoke

    image-20200318013340997


    一个实例

    先定义一个接口

    package tk.suyuesheng.proxy;
    
    /**
     * 一个sale接口
     * @author 苏月晟
     */
    public interface ISale {
        //定义两个方法,一个有返回值,一个没有返回值
    
        /**
         * 进货
         * @param goodsName 商品名称
         */
        void get(String goodsName);//进货
    
        /**
         * 数钱 注:成本一律6块2
         * @param money 收的钱
         * @return
         */
        double count(double money);//数钱
    }
    
    

    再定义一个实现接口的真实类

    package tk.suyuesheng.proxy;
    //代理设计模式的真实对象
    public class Saleimpl implements ISale {
        @Override
        public void get(String goodsName) {
            System.out.println("商品名称是:"+goodsName);
        }
    
        @Override
        public double count(double money) {
            System.out.println("开始数钱");
            double count = money - 6.2;
            return count;//返回真正的利润
        }
    }
    

    至关重要的一步,定义一个invocation handler object,即中间类,或者调用处理器,这个要实现InvocationHandler接口。中间类的作用是在原有的真实类上定义要增加的东西,比如说要在真实类的所有方法执行前都打印一句before。

    package tk.suyuesheng.proxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    /**
     * 中介类,或称作调用处理器,或乘坐调用帮手
     */
    public class SaleProxy implements InvocationHandler {
        ISale ss;//真实对象
        public SaleProxy(){
    
        }
        public SaleProxy(ISale ss){
            //调用处理器要指定真实对象,这是必要的
            this.ss=ss;
        }
    
        /*
            代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
                参数:
                    1. proxy:代理对象
                    2. method:代理对象调用的方法,被封装为的对象
                    3. args:代理对象调用的方法时,传递的实际参数
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println(method.getName());
            System.out.println("before");
            Object invoke = method.invoke(ss, args);//执行真实类的方法,返回真实类的返回值,ss是真实类,args是参数
            System.out.println("after");
            return invoke;
        }
    }
    
    

    获得代理对象,并执行代理对象的方法

    package tk.suyuesheng.proxy;
    
    import java.lang.reflect.Proxy;
    
    public class Main {
        public static void main(String[] args) {
            System.out.println(ISale.class.getInterfaces());
            System.out.println(ISale.class);
            SaleProxy saleProxy = new SaleProxy(new Saleimpl());
            ISale o = (ISale)Proxy.newProxyInstance(ISale.class.getClassLoader(), new Class[]{ISale.class}, saleProxy);
            o.get("家电");
            double count = o.count(12.5);
            System.out.println(count);
        }
    }
    
    

    ISale o = (ISale)Proxy.newProxyInstance(ISale.class.getClassLoader(), new Class[]{ISale.class}, saleProxy);的解释:

    ​ 此举是为获取代理类。ISale.class.getClassLoader()指定了类的加载器,也就是说指定了代理类代理的是谁?返回的是谁的类。new Class[]{ISale.class}是接口列表,指定了被代理的类实现了哪些接口。saleProxy是中间类,定义了在真实类基础上被修改的内容。

    简书 动态代理模式

    image-20200318132908799

    ​ 即返回了一个实现了ISale接口的ISale实例化对象,且ISale实例化对象的方法已经按照saleProxy里定义的内容所修改增加。

  • 相关阅读:
    对于捐赠承诺和劳务捐赠,不予以确认,但应在会计报表附注中披露
    R语言代写线性混合效应模型Linear Mixed-Effects Models的部分折叠Gibbs采样
    matlab代写MCMC贝叶斯方法用于加筋复合板的冲击载荷识别
    R语言代写dplyr-高效的数据变换与整理工具
    GIS代写遥感数据可视化评估:印度河流域上部的积雪面积变化
    R语言代写向量自回归模型(VAR)及其实现
    r语言代写实现似然的I(2)协整VAR模型弱外生性推理
    python代写缺失值处理案例分析:泰坦尼克数据
    Python代写高性能计算库——Numba
    matlab递归神经网络RNN实现:桨距控制控制风力发电机组研究
  • 原文地址:https://www.cnblogs.com/sogeisetsu/p/12515103.html
Copyright © 2011-2022 走看看