zoukankan      html  css  js  c++  java
  • 对于反射的一些总结之动态代理

    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 }
  • 相关阅读:
    在VS2010下,用QT,创建一个Opencv应用程序
    SNR(信噪比)与 特定分布噪声的关系初探
    Qt学习笔记_FindDialog
    关于reduced rank regression的一些看法
    实时摄像头人眼跟踪: RealTime Tracking Of Human Eyes Using a Webcam
    L1_APG_Tracker实现代码剖析
    CVPR2013 感兴趣论文汇总
    使用PowerDesigner 15对现有数据库进行反向工程(图解教程)(转)
    大数据量高并发的数据库优化
    rtmp和rtsp的区别
  • 原文地址:https://www.cnblogs.com/Vincent-NMT/p/6083142.html
Copyright © 2011-2022 走看看