设计模式之动态代理



一、代理的简要介绍
  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类图:

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM