• 设计模式之动态代理



    一、代理的简要介绍
      1、ProxyPattern(即:代理模式),23种常用的面向对象软件的设计模式之一

         2、代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

    ​     3、作用:增强一个类中的某个方法.对程序进行扩展,Spring框架中AOP。

    二、动态代理介绍
    1、动态代理:
    • ​ 动态代理它可以直接给某一个目标(被代理 对象)对象(实现了某个或者某些接口)生成一个代理对象,而不需要代理类存在,如上图中经理人需要存在。
    • ​ 动态代理与代理模式原理是一样的,只是它没有具体的代理类,直接通过反射生成了一个代理对象

     2、动态代理的分类

    • jdk提供一个Proxy类可以直接给实现接口类的对象直接生成代理对象 API: 调用, 缺少什么参数,传什么
    • ​ spring中动态代理:cglib 继承
    3、动态代理作用
    • 最终是学习AOP(面向切面编程),它与装饰者模式有点相似,它比装饰者模式还要灵活!

       三、jdk中的动态代理

      1、Java.lang.reflect.Proxy类可以直接生成一个代理对象

    • Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)生成一个代理对象

      • 参数1:ClassLoader loader 代理对象的类加载器 一般使用被代理对象的类加载器

      • 参数2:Class<?>[] interfaces 代理对象的要实现的接口 一般使用的被代理对象实现的接口

      • 参数3:InvocationHandler h (接口)执行处理类

    • InvocationHandler中的invoke(Object proxy, Method method, Object[] args)方法:调用代理类的任何方法,此方法都会执行

      • 参数3.1:代理对象(慎用)

      • 参数3.2:当前执行的方法

      • 参数3.3:当前执行的方法运行时传递过来的参数

        • 返回值:当前方法执行的返回值

    2、Proxy.newProxyInstance方法参数介绍
    • ClassLoader:类加载器!
      • 它是用来加载器的,把.class文件加载到内存,形成Class对象!

    • Class[] interfaces:指定要实现的接口们
    • InvocationHandler:代理对象的所有方法(个别不执行,getClass())都会调用InvocationHandler的invoke()方法。
    3、InvocationHandler方法参数介绍

      public Object invoke(Object proxy, Method method, Object[] args);

      这个invoke()方法在什么时候被调用!在调用代理对象所实现接口中的方法时

    • Object proxy:当前对象,即代理对象!在调用谁的方法!
    • Method method:当前被调用的方法(目标方法)
    • Object[] args:实参!
    4、简单示例
     1 import org.junit.Test;
     2 import java.lang.reflect.InvocationHandler;
     3 import java.lang.reflect.Method;
     4 import java.lang.reflect.Proxy;
     5 
     6 public class ProxyDemo {
     7     @Test
     8     public void test(){
     9         Person woman = new Woman();
    10         Person person =(Person) Proxy.newProxyInstance(woman.getClass().getClassLoader(),
    11                 woman.getClass().getInterfaces(),
    12                 new InvocationHandler() {
    13                     @Override
    14                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    15                         //增强sleep方法
    16                         if ("sleep".equals(method.getName())) {
    17                             System.out.println("大字睡姿.....");
    18                             return null;
    19                         }
    20                         return method.invoke(woman, args);
    21                     }
    22                 });
    23         person.eat();
    24         person.sleep();
    25         String s = person.run("快步跑");
    26         System.out.println(s);
    27     }
    28 
    29     interface Person{
    30         void eat();
    31         void sleep();
    32         String run(String state);
    33     }
    34 
    35     class Woman implements Person{
    36 
    37         @Override
    38         public void eat() {
    39             System.out.println("小口吃...");
    40         }
    41 
    42         @Override
    43         public void sleep() {
    44             System.out.println("淑女睡...");
    45         }
    46 
    47         @Override
    48         public String run(String state) {
    49             return "Woman" + state + "......";
    50         }
    51     }
    52 }
    四、动态代理模型
    • 目标对象:被增强的对象
    • 代理对象:需要目标对象,然后在目标对象上添加了增强后的对象!
    • 目标方法:增强的内容
    • 代理对象 = 目标对象 + 增强

    五、案例
    案例1:Waiter
     1 package demo2;
     2 
     3 import org.junit.Test;
     4 import java.lang.reflect.InvocationHandler;
     5 import java.lang.reflect.Method;
     6 import java.lang.reflect.Proxy;
     7 
     8 public class Demo2 {
     9     @Test
    10     public void fun1() {
    11         Waiter manWaiter = new ManWaiter();
    12         /*
    13         * 给出三个参数,来创建方法,得到代理对象
    14         * */
    15         ClassLoader loader = this.getClass().getClassLoader();
    16         Class[] interfaces = {Waiter.class};
    17         InvocationHandler h = new WaiterInvocationHandler(manWaiter);//参数manWaiter类表示目标对象
    18         //得到代理对象,代理对象就是在目标对象的基础上进行了增强的对象!
    19         Waiter waiterProxy = (Waiter) Proxy.newProxyInstance(loader,interfaces,h);
    20         waiterProxy.serve();//前面添加"你好",后面添加"再见"
    21 
    22     }
    23 }
    24 class WaiterInvocationHandler implements InvocationHandler {
    25     private Waiter waiter;//目标对象
    26 
    27     public WaiterInvocationHandler(Waiter waiter) {
    28         this.waiter = waiter;
    29     }
    30     @Override
    31     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    32         System.out.println("您好!");
    33         this.waiter.serve();//调用目标对象的目标方法
    34         System.out.println("再见!");
    35         return null;
    36     }
    37 }
    1 package demo2;
    2 
    3 public class ManWaiter implements Waiter {
    4     @Override
    5     public void serve() {
    6         System.out.println("服务中...");
    7     }
    8 }
    1 package demo2;
    2 
    3 //服务
    4 public interface Waiter {
    5     //服务
    6     public void serve();
    7 }

     案例2:

     1 /**
     2  * 目标是让目标对象和增强都可以切换!
     3  */
     4 public class Demo3 {
     5     @Test
     6     public void fun1() {
     7         ProxyFactory factory = new ProxyFactory();
     8         factory.setTargetObject(new ManWaiter());
     9         factory.setBeforeAdvice(new BeforeAdvice() { //设置前置增强
    10             @Override
    11             public void before() {
    12                 System.out.println("您好!");
    13             }
    14         });
    15         factory.setAfterAdvice(new AfterAdvice() { //设置后置增强
    16             @Override
    17             public void after() {
    18                 System.out.println("再见!");
    19             }
    20         });
    21 
    22         Waiter waiter = (Waiter) factory.createProxy();
    23         waiter.serve();
    24     }
    25 }
     1 package demo3;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 import java.lang.reflect.Proxy;
     6 
     7 /**
     8  * 它用来生成代理对象
     9  * 它需要所有的参数
    10  *    目标对象
    11  *    增强
    12  */
    13 /*
    14 * 1、创建代理工厂
    15 * 2、给工厂设置三样东西:
    16 *   目标对象:setTargetObject(XXX);
    17 *   前置增强:setBeforeAdvice(该接口的实现)
    18 *   后置增强:setAfterAdvice(该接口的实现)
    19 * 3、调用createProxy()得到代理对象
    20 *   执行代理对象方法时:
    21 *       执行BeforeAdvice的before()
    22 *       目标对象的目标方法
    23 *       执行AfterAdvice的after()
    24 * */
    25 public class ProxyFactory {
    26     private Object targetObject;//目标对象
    27     private BeforeAdvice beforeAdvice;//前置增强
    28     private AfterAdvice afterAdvice;//后置增强
    29 
    30     //用来生成代理对象
    31     public Object createProxy() {
    32         /*
    33         * 1、给出三大参数
    34         * */
    35         ClassLoader loader = this.getClass().getClassLoader();
    36         Class[] interfaces = targetObject.getClass().getInterfaces();
    37         InvocationHandler h = new InvocationHandler() {
    38             @Override
    39             public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    40                 /*
    41                 * 在调用代理对象的方法时会执行这里的内容
    42                 * */
    43                 //执行前置增强
    44                 if (beforeAdvice != null) {
    45                     beforeAdvice.before();
    46                 }
    47                 Object result = method.invoke(targetObject,args);//执行目标对象的目标方法
    48                 //执行后置增强
    49                 if (afterAdvice != null) {
    50                     afterAdvice.after();
    51                 }
    52                 return result;
    53             }
    54         };
    55         //2、得到代理对象
    56         Object proxObject = Proxy.newProxyInstance(loader,interfaces,h);
    57         return proxObject;
    58     }
    59     public Object getTargetObject() {
    60         return targetObject;
    61     }
    62     public void setTargetObject(Object targetObject) {
    63         this.targetObject = targetObject;
    64     }
    65     public BeforeAdvice getBeforeAdvice() {
    66         return beforeAdvice;
    67     }
    68     public void setBeforeAdvice(BeforeAdvice beforeAdvice) {
    69         this.beforeAdvice = beforeAdvice;
    70     }
    71     public AfterAdvice getAfterAdvice() {
    72         return afterAdvice;
    73     }
    74     public void setAfterAdvice(AfterAdvice afterAdvice) {
    75         this.afterAdvice = afterAdvice;
    76     }
    77 }
    1 /**
    2  * 前置增强
    3  */
    4 public interface BeforeAdvice {
    5     public void before();
    6 }
    1 /**
    2  * 后置增强
    3  */
    4 public interface AfterAdvice {
    5     public void after();
    6 }

     案例2类图:

  • 相关阅读:
    阅读进度条的实现
    获取radio选中的值
    Vue的学习(六)
    Vue的学习(三)
    C#委托详解
    C#泛型和非泛型
    C#装箱和拆箱
    C#内存泄漏的事例
    C#windows服务开发(一)
    C#windows服务开发
  • 原文地址:https://www.cnblogs.com/gdwkong/p/8035120.html
Copyright © 2020-2023  润新知