对于反射的一些总结之动态代理

1、为什么需要使用代理?

    1.1、 首先我们需要了解一下什么是横切关注点?

         横切关注点: 跨越应用程序多个模块的功能.

      1.2、非模块化的横切关注点将会导致的问题:

    ①  、代码混乱: 每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点.

    ②  、代码分散: 以日志需求为例, 只是为了满足这个单一需求, 就不得不在多个模块里多次重相复同的日志代码. 如果日志需求发生变化, 必须修改所有模块. 这些类似的需求包括验证, 事务等.

    ③  、代码膨胀:越来越多的非业务需求(日志和验证)加入后, 原有的方法急剧膨胀.

  1.3、如何解决:

  • AOP(Aspect Orient Program, 面向切面编程)(Spring 框架就是使用AOP)
  • 使用动态代理模块化横切关注点:代理设计模式的原理:使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时将方法调用转到原始对象上.

  1.4、如何创建动态代理:

    ①  、Proxy 提供用于创建动态代理类和代理对象的静态方法, 它也是所有动态代理类的父类.

    ②  、Proxy 提供了两个方法来创建动态代理类和动态代理实例

 我们通过代码来进行理解:

接口的代码:

 1 package cn.vincent.porxy;
 2 
 3 public interface ArithmeticCalculator {
 4 
 5      int add(int i, int j);
 6 
 7      int sub(int i, int j);
 8 
 9     void mul(int i, int j);
10 
11     void div(int i, int j);
12 
13 
14 }

接口实现类的代码:

 1 package cn.vincent.porxy;
 2 
 3 public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
 4 
 5      @Override
 6 
 7     public int add(int i, int j) {
 8 
 9         return i + j;
10 
11     } 
12 
13     @Override
14 
15     public int sub(int i, int j) {
16 
17        return i - j;
18 
19     } 
20 
21     @Override
22 
23     public void mul(int i, int j) {
24 
25         System.out.println(i * j);
26 
27     }
28 
29     @Override
30 
31     public void div(int i, int j) {
32 
33        System.out.println(i / j);
34 
35     }
36 
37 }

动态代理类实现的代码:

  1 package cn.vincent.porxy;
  2  
  3 import java.lang.reflect.InvocationHandler;
  4 
  5 import java.lang.reflect.Method;
  6 
  7 import java.lang.reflect.Proxy;
  8 
  9 import org.junit.Test;
 10 
 11 
 12 public class TestPorxy {
 13 
 14 /**
 15 
 16 * 关注点:
 17 
 18 *
 19 
 20 * 1.获取需要被代理的目标对象。
 21 
 22 *
 23 
 24 * 2. Proxy.newProxyInstance(loader, interfaces, h);
 25 
 26 *      public static Object newProxyInstance(ClassLoader loader,
 27 
 28 *                                          Class<?>[] interfaces,
 29 
 30 *                                         InvocationHandler h)
 31 
 32 * 通过使用代理类调用 静态方法 newProxyInstance 返回一个指定接口的代理类实例,
 33 
 34 * 一般情况下其返回的是被代理的目标对象接口类型的!该接口可以将方法调用指派到指* 定的调用处理程序。
 35 
 36 *
 37 
 38 * 对于 newProxyInstance 方法中参数都代表什么?
 39 
 40 *   ClassLoader loader : 类加载器通常使用和被代理的对象的类加载器相同.
 41 
 42 *  
 43 
 44 * Class<?>[] interfaces:该参数必须是一个接口类型的数组.其中若代理对象不需要
 45 
 46 * 额外实现被代理的目标对象实现的接口外的
 47 
 48 * 额外的接口类型,可以使用 target.getClass().getInterfaces(),来表示目标对象*实现的接口
 49 
 50 *
 51 
 52 * InvocationHandler h :通常使用匿名内部类的方式。
 53 
 54 *   对于 匿名内部类InvocationHandler中的invoke 方法 中的参数。
 55 
 56 *  public Object invoke(Object proxy, Method method, Object[] args) *throws Throwable {
 57 
 58 *             
 59 
 60 *                 Object result = method.invoke(target, args);
 61 
 62 *                 return result;
 63 
 64 *          }
 65 
 66 *    Object proxy  : 指的是正在被返回的那个代理对象,一般不使用!
 67 
 68 *    Object[] args : 传入的参数。
 69 
 70 *    Method method : 通过调用 invoke(Object obj, Object ... args),将被代
 71 
 72 *     理的对象及参数传入,
 73 
 74 *          method.invoke(target, args);
 75 
 76 *    实现动态代理。
 77 
 78 */
 79 
 80     @Test
 81 
 82     public void test() {
 83  
 84 
 85        ArithmeticCalculator target = new ArithmeticCalculatorImpl();
 86 
 87        Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(),
 88 
 89 //                   new Class[]{ArithmeticCalculator.class},
 90 
 91                      target.getClass().getInterfaces(),
 92 
 93                      new InvocationHandler() {
 94                  
 95                   @Override
 96 
 97                   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 98 
 99                   Object result = method.invoke(target, args);
100 
101                      return result;
102 
103                   }
104 
105               });
106 
107        ArithmeticCalculator arithmeticCalculator = (ArithmeticCalculator) proxy;
108 
109        int result = arithmeticCalculator.add(1, 1);
110       
111 
112        System.out.println(result);
113 
114     }
115 
116 }

 

posted @ 2016-11-20 18:42  Vincent_NMT  阅读(178)  评论(0编辑  收藏  举报