为什么要使用动态代理?

为什么要使用动态代理?也就是说它解决了什么问题。 
假如现在有这样的需求 
需求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);
  • 1
  • 2
  • 3
  • 4
  • 5

}

**然后写接口的实现类**

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方法执行
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8


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

文章标签:  class 需求

猜你喜欢

转载自blog.csdn.net/qq_17312239/article/details/80686646