今天看啥  ›  专栏  ›  zheng_zq

Filter学习笔记(五) 动态代理

zheng_zq  · 简书  ·  · 2020-02-10 17:39

增强对象的功能

我们需要用到设计模式去实现增强对象的功能,23种设计模式中的 装饰模式 代理模式 都可以实现,我们使用 代理模式

代理模式

以下以购买笔记本电脑为情景



不考虑网购的情况,用户买电脑无需跑到北京去购买,只需要去本地的代理商购买。反过来思考,相当于增强了北京联系公司的功能。

  • 概念
    1.真实对象:被代理的对象(北京联想公司)
    2.代理对象:(西安联想代理商)
    3.代理模式: 代理对象 代理 真实对象 ,达到增强真实对象功能的目的
  • 实现方式
    1.静态代理:有一个类文件描述代理模式(即代理商固定就那几家)
    2.动态代理:在内存中形成代理类(你在哪里购买电脑,哪里就动态生成代理商)
    注意 :我们使用动态代理模式
  • 实现步骤
    1.代理模式和真实对象实现相同的接口
    2.使用 Proxy.newProxyInstance() 方法获取代理对象
    3.使用代理对象调用方法
    4.增强方法
  • 增强方式
    1.增强参数列表
    2.增强返回值类型
    3.增强方法执行逻辑

代码实现(代理对象实现基本业务功能)

注意 Proxy.newProxyInstance() 方法需要传的三个参数如下:


1.类加载器:真实对象.getClass().getClassLoader()
2.接口数组:真实对象.getClass().getInterfaces()
3.处理器:new InvocationHandler()
注意 :代理对象调用的所有方法都会触发 invoke() 方法执行,方法需要传递的三个参数如下:
1.proxy:代理对象
2.method:代理对象调用的方法被封装成Method对象
3.args:代理对象调用方法时,传递的实际参数
注意 :代理对象并不能直接执行真实对象的方法,就像西安联想代理商不能直接出售电脑,需要从北京联想公司进货。所以代理对象需要传递真实对象去调用方法

SaleComputer.java

public interface SaleComputer {
    public String sale(double money);

    public void show();
}

Lenvo.java

/**
 * 真实类
 */
public class Lenovo implements SaleComputer {
    @Override
    public String sale(double money) {
        System.out.println("花了" + money + "元购买了一台联想电脑");
        return "联想电脑";
    }

    @Override
    public void show() {
        System.out.println("展示电脑....");
    }
}

ProxyTest.java

public class ProxyTest {
    public static void main(String[] args) {
        //1.创建真实对象
        Lenovo lenovo = new Lenovo();

        //2.动态代理增强Lenovo对象
        /*
        三个参数:
            1.类加载器:真实对象.getClass().getClassLoader()
            2.接口数组:真实对象.getClass().getInterfaces()
            3.处理器:new InvocationHandler()
         */
        SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(),
                lenovo.getClass().getInterfaces(), new InvocationHandler() {
                    /*
                    代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
                        参数:
                            1.proxy:代理对象
                            2.method:代理对象调用的方法被封装成Method对象
                            3.args:代理对象调用方法时,传递的实际参数
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //使用真实对象调用该方法
                        Object obj = method.invoke(lenovo, args);
                        return obj;
                    }
                });

        //3.调用方法
        String computer = proxy_lenovo.sale(8000);
        System.out.println(computer);
    }
}

此时执行ProxyTest会发现代理对象能够 正常实现业务需求

代码实现(用代理对象增强真实对象的功能)

  • 增强参数列表
    西安代理商可以以 更便宜的价格 从北京联想公司进货,假设代理商只需要用 出售价的85% 的价格进货
@Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //判断是否是sale方法
                        if (method.getName().equals("sale")) {
                            //增强参数
                            double money = (double) args[0];
                            money = money * 0.85;
                            //使用真实对象调用该方法
                            Object obj = method.invoke(lenovo, money);
                            return obj;
                        } else {
                            Object obj = method.invoke(lenovo, args);
                            return obj;
                        }
                    }

用户使用了8000元购买,所以代理商 赚了15% 的利润

  • 增强返回值类型
    由于代理商赚了 15% 的利润,所以代理商可以附赠一些赠品
  • 增强方法执行逻辑
    比如说提供 售前服务



原文地址:访问原文地址
快照地址: 访问文章快照