代理模式之动态代理

Posted t-mmy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代理模式之动态代理相关的知识,希望对你有一定的参考价值。

代理设计模式:使用代理对象将原始对象包装起来,然后用代理对象取代原始对象。任何对原始对象的调用都要通过代理对象。代理对象决定是否以及何时将方法调用转到原始对象上。

 

技术图片

 

 

 

1)接口MathInterface.java:

public interface MathInterface {

   //加

   public int add(int a,int b);

   //减

   public int sub(int a,int b);

   //乘

   public int mul(int a,int b);

   //除

   public int div(int a,int b);

}

2)实现类MathImpl.java:

 public class MathImpl implements MathInterface {

 

   @Override

   public int add(int a, int b) {

      int result = a + b;

      return result;

   }

 

   @Override

   public int sub(int a, int b) {

      int result = a - b;

      return result;

   }

 

   @Override

   public int mul(int a, int b) {

      int result = a * b;

      return result;

   }

 

   @Override

   public int div(int a, int b) {

      int result = a / b;

      return result;

   }

}

3)MathInterfaceLogProxy.java:

/*

 * 生成MathInterface的代理对象的工厂类:

 */

public class MathInterfaceLogProxy {

 

   //1>成员变量MathInterface的对象math,要被代理的对象(原始对象)

   private MathInterface math;

  

   /*

    * 2>在构造器中将要被代理的对象传给工厂类对象

    */

   public MathInterfaceLogProxy(MathInterface math){

      this.math = math;

   }

  

   /*

    * 3>获取代理对象的工厂方法,返回值还是MathInterface类型

    */

   public MathInterface getMathInterfaceProxy(){

      //1)声明一个MathInterface对象,即接收最终生成且要被返回的代理对象

      MathInterface proxy = null;

      //2)获取被代理的对象的类加载器,表示生成的代理对象由哪个类加载负责加载

      ClassLoader loader = math.getClass().getClassLoader();

      //3)指定生成的代理对象的类型,代理对象就由此可知道所要代理的原始对象中的所有方法

      Class[] mathInterfaceClass = new Class[]{MathInterface.class};

      //4)匿名内部类,当调用生成的代理对象所代理的原始对象的任何方法时执行的代码

      InvocationHandler handler = new InvocationHandler() {

          /**

           * invoke方法的参数:

           * Object proxy:表示代理对象,该对象在invoke方法中一般不使用

           * Method method:表示代理对象正在调用的所代理的对象的方法

           * Object[] params:表示代理对象正在调用的所代理的对象的方法的参数

           */

          @Override

          public Object invoke(Object proxy, Method method, Object[] params)

                throws Throwable {

            

             //代理对象正在调用的方法名

             String methdoName = method.getName();

             //执行前的日志

             System.out.println("日志: The method "+methdoName+" begin with "+Arrays.toString(params));

             //执行方法

             int result = (int) method.invoke(math, params);

             //执行后的日志

             System.out.println("日志: The method "+methdoName+" end with "+result);

            

             return result;

          }

      };

     

      /*

       * 5)实例化代理对象:

       *   调用java.lang.reflect.Proxy类的静态方法newProxyInstance()

       *   参数一ClassLoader:生成代理对象使用的类加载器

       *   参数二Class[]:指定生成的代理对象的类型

       *   参数三InvocationHandler:指定当具体调用生成的代理对象所代理的对象的方法时执行的内容。

       *   本质是调用了参数InvocationHandler对象的invoke()方法

       */

      proxy = (MathInterface) Proxy.newProxyInstance(loader, mathInterfaceClass, handler);

     

      //6)返回生成的代理对象

      return proxy;

   }

}

4)测试:

package com.mmy.aop.helloworld;

 

public class Test {

 

   public static void main(String[] args) {

     

      //1.创建方法中没有日志代码的MathInterface实现类MathImpl对象(被代理的对象)

      MathInterface math = new MathImpl();

      //2.创建生成MathInterface的代理对象的工厂类对象,并传入被代理的对象

      MathInterfaceLogProxy factory = new MathInterfaceLogProxy(math);

      //3.调用工厂类对象的工厂方法,生成MathInterface的代理对象

      MathInterface proxy = factory.getMathInterfaceProxy();

      //4.测试

      /*

       * 日志:The method add begin with [2,3]

          日志:The method add end with 5

          5

       */

      int result = proxy.add(2, 3);

      System.out.println(result);

      /*

       * 日志:The method mul begin with [4,5]

          日志:The method mul end with 20

          20

       */

      result = proxy.mul(4, 5);

      System.out.println(result);

   }

}

以上是关于代理模式之动态代理的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式-代理模式之动态代理(附源代码分析)

#yyds干货盘点# 设计模式之代理模式:动态代理

系统架构设计——设计模式之代理模式CGLIB动态代理实现

代理模式之JDK动态代理

设计模式之动态代理模式

Spring之静态/动态代理模式