为什么要使用动态代理?

来源:互联网 发布:2017年网络暴力事例 编辑:程序博客网 时间:2024/06/05 04:07

为什么要使用动态代理?也就是说它解决了什么问题。
假如现在有这样的需求
需求1-日志:在程序执行期间追踪正在发生的活动
需求2-验证:希望计算器只能处理正数的运算

比如:一个加减乘除 运算的类 可能会这么写代码
这里写图片描述

这样的代码有两个致命的问题。

  1. 代码混乱:越来越多的非业务需求(日志和验证等)加入后, 原有的业务方法急剧膨胀.
    每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点.
    比如:每新添加了方法,还得继续写日志和验证
  2. 代码分散: 以日志需求为例, 只是为了满足这个单一需求, 就不得不在多个模块(方法)里多次重复相同的日志代码. 如果日志需求发生变化,
    必须修改所有模块.
    比如:现在此类的方法里都显示方法名,那么每个方法都得一个一个改

那么现在加入动态代理能解决上述问题
这里写图片描述

那么上代码
首先写个接口,因为后面代理类要用接口得到实现类的方法
public interface ArithmeticCalculator {

int add(int i, int j);int sub(int i, int j);int mul(int i, int j);int div(int i, int j);

}

**然后写接口的实现类**public class ArithmeticCalculatorImpl implements ArithmeticCalculator {    @Override    public int add(int i, int j) {        int result = i + j;        return result;    }    @Override    public int sub(int i, int j) {        int result = i - j;        return result;    }    @Override    public int mul(int i, int j) {        int result = i * j;        return result;    }    @Override    public int div(int i, int j) {        int result = i / j;        return result;    }}**然后写实现动态代理的类**import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.Arrays;public class ArithmeticCalculatorLoggingProxy {    //要代理的对象    private ArithmeticCalculator target;    public ArithmeticCalculatorLoggingProxy(ArithmeticCalculator target) {        super();        this.target = target;    }    //返回代理对象    public ArithmeticCalculator getLoggingProxy(){        ArithmeticCalculator proxy = null;        ClassLoader loader = target.getClass().getClassLoader();        Class [] interfaces = new Class[]{ArithmeticCalculator.class};//这个class是代理对象实现的接口        InvocationHandler h = new InvocationHandler() {            /**             * proxy: 代理对象。 一般不使用该对象             * method: 正在被调用的方法             * args: 调用方法传入的参数             */            @Override            public Object invoke(Object proxy, Method method, Object[] args)                    throws Throwable {                String methodName = method.getName();                //打印日志                System.out.println("[before] The method " + methodName + " begins with " + Arrays.asList(args));                //调用目标方法                Object result = null;                try {                    //前置通知                    result = method.invoke(target, args);                    //返回通知, 可以访问到方法的返回值                } catch (NullPointerException e) {                    e.printStackTrace();                    //异常通知, 可以访问到方法出现的异常                }                //后置通知. 因为方法可以能会出异常, 所以访问不到方法的返回值                //打印日志                System.out.println("[after] The method ends with " + result);                return result;            }        };        /**         * loader: 代理对象使用的类加载器。          * interfaces: 指定代理对象的类型. 即代理代理对象中可以有哪些方法.          * h: 当具体调用代理对象的方法时, 应该如何进行响应, 实际上就是调用 InvocationHandler 的 invoke 方法         */        proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);        return proxy;    }}最后调用main方法执行
public static void main(String[] args) {    ArithmeticCalculator arithmeticCalculator = new ArithmeticCalculatorImpl();                  arithmeticCalculator = ArithmeticCalculatorLoggingProxy(arithmeticCalculator).getLoggingProxy();    int result = arithmeticCalculator.add(11, 12);    System.out.println("result:" + result);    result = arithmeticCalculator.div(21, 3);    System.out.println("result:" + result);

}
“`
动态代理执行结果
这里写图片描述

0 0
原创粉丝点击