spring设计模式_代理模式

代理模式应该是Spring核心设计模式之一了

先说下代理模式特性:

  1.有代理人和被代理人

  2.对于被代理的人来说,这件事情是一定要做的,但是我又不想做,所有就找代理人来做。

  3.需要获取到被代理人的个人资料。

 

Spring中的代理模式是声明式事务 (AOP)

 

代理模式代码中的使用

  1.日志监听

  2.开启,关闭事务

  3.等等

 

现实中的例子:

  黄牛:我需要买票又不想排队,黄牛拿着我的个人信息代替我买票。。emmmmm不合法,但确实是代理模式

  相亲: 我需要女朋友又不主动找女朋友,所以媒婆拿着我的个人条件,代替我去找女朋友??????总感觉哪里怪怪的

 

GitHub源码地址:https://github.com/wujiachengSH/WjcProxyDemo

 

下面我们来举个栗子看下代码中的代理是什么样子的

 咳咳,来个找对象吧

先定义个接口

package com.wjc.proxy;

public interface People {

	String getHeight();
	
	String getSex();
	
	//择偶标准
	void getStandardsOfChoosingSpouse();
	
}

 

 来个实现类

 1 package com.wjc.proxy;
 2 
 3 public class Wjc implements People {
 4 
 5     private String height = "170";
 6     private String Sex = "男";
 7     
 8     @Override
 9     public String getHeight() {
10         // TODO Auto-generated method stub
11         return height;
12     }
13 
14     @Override
15     public String getSex() {
16         // TODO Auto-generated method stub
17         return Sex;
18     }
19 
20     @Override
21     public void getStandardsOfChoosingSpouse() {
22         // TODO Auto-generated method stub
23         System.out.println("性别男,爱好女");
24         System.out.println("不想努力了,求富婆包养");
25         
26     }
27 
28     
29     
30 }

 

 来个代理类,代替我调用我自己,传说中的害羞。。噗

 1 package com.wjc.proxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 import java.lang.reflect.Proxy;
 6 
 7 public class MatchMaker implements InvocationHandler {
 8     // 拿到被代理的对象
 9     private People target;
10 
11     // 获取被代理对象
12     public Object getInstance(People target) throws Exception {
13         this.target = target;
14         Class clazz = target.getClass();
15         return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
16     }
17 
18     @Override
19     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
20         System.out.println("-------这是一位"+this.target.getSex()+"性-------");
21         
22         method.invoke(this.target, args);
23         System.out.println("找富婆是要付出代价的");
24 
25         return null;
26     }
27 
28 }

 

测试一下

 1 package com.wjc.proxy;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5 
 6         try {
 7             People instance = (People) new MatchMaker().getInstance(new Wjc());
 8             instance.getStandardsOfChoosingSpouse();
 9             
10             instance.getHeight();
11         } catch (Exception e) {
12             // TODO Auto-generated catch block
13             e.printStackTrace();
14         }
15 
16     }
17 }

测试结果

 

 通过这个简单的栗子,看到所谓的代理,其实就是方法增强,嗯,可以拿到对象的所有方法,并且以一定顺序来执行。

 

那么问题就来了,到底是怎么实现的呢?

 1 package com.wjc.proxy;
 2 
 3 public class Test2 {
 4     public static void main(String[] args) {
 5 
 6         try {
 7             Wjc wjc = new Wjc();
 8             People instance = (People) new MatchMaker().getInstance(wjc);
 9             System.out.println(wjc.getClass());
10             System.out.println(instance.getClass());
11             
12         } catch (Exception e) {
13             // TODO Auto-generated catch block
14             e.printStackTrace();
15         }
16 
17     }
18 }

执行结果

可以看到已经不是原来的类了

在代理的过程中,会使用反射的技巧,重新生成一个类!

大致代理流程如下所示

//1.拿到被代理对象的引用,然后获取它的接口
//2.JDK代理重新生成一个类,同时实现我们给的代理对象所实现的接口
//3.把被代理对象的引用也拿到了
//4.重新动态生成一个class字节码
//5.然后编译

  

 我们将打印并反编译出来,看看到底都干啥了

 打印类方法

1         byte[] data = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{People.class});
2             FileOutputStream os = new FileOutputStream("E:/$Proxy0.class");
3             os.write(data);
4             os.close();

 

通过小工具(luyten) 下载地址:https://github.com/deathmarine/Luyten/releases/tag/v0.5.4

可以看到,创建的类获取了对象的hashcode,equals,toString和其自有方法来创建了一个新类

所有在使用代理时,此类就是代理人,被他反射的方法的对象就是被代理人

  1 import com.wjc.proxy.*;
  2 import java.lang.reflect.*;
  3 
  4 public final class $Proxy0 extends Proxy implements People
  5 {
  6     private static Method m1;
  7     private static Method m4;
  8     private static Method m2;
  9     private static Method m3;
 10     private static Method m5;
 11     private static Method m0;
 12     
 13     public $Proxy0(final InvocationHandler invocationHandler) {
 14         super(invocationHandler);
 15     }
 16     
 17     public final boolean equals(final Object o) {
 18         try {
 19             return (boolean)super.h.invoke(this, $Proxy0.m1, new Object[] { o });
 20         }
 21         catch (Error | RuntimeException error) {
 22             throw;
 23         }
 24         catch (Throwable t) {
 25             throw new UndeclaredThrowableException(t);
 26         }
 27     }
 28     
 29     public final String getSex() {
 30         try {
 31             return (String)super.h.invoke(this, $Proxy0.m4, null);
 32         }
 33         catch (Error | RuntimeException error) {
 34             throw;
 35         }
 36         catch (Throwable t) {
 37             throw new UndeclaredThrowableException(t);
 38         }
 39     }
 40     
 41     public final String toString() {
 42         try {
 43             return (String)super.h.invoke(this, $Proxy0.m2, null);
 44         }
 45         catch (Error | RuntimeException error) {
 46             throw;
 47         }
 48         catch (Throwable t) {
 49             throw new UndeclaredThrowableException(t);
 50         }
 51     }
 52     
 53     public final void getStandardsOfChoosingSpouse() {
 54         try {
 55             super.h.invoke(this, $Proxy0.m3, null);
 56         }
 57         catch (Error | RuntimeException error) {
 58             throw;
 59         }
 60         catch (Throwable t) {
 61             throw new UndeclaredThrowableException(t);
 62         }
 63     }
 64     
 65     public final String getHeight() {
 66         try {
 67             return (String)super.h.invoke(this, $Proxy0.m5, null);
 68         }
 69         catch (Error | RuntimeException error) {
 70             throw;
 71         }
 72         catch (Throwable t) {
 73             throw new UndeclaredThrowableException(t);
 74         }
 75     }
 76     
 77     public final int hashCode() {
 78         try {
 79             return (int)super.h.invoke(this, $Proxy0.m0, null);
 80         }
 81         catch (Error | RuntimeException error) {
 82             throw;
 83         }
 84         catch (Throwable t) {
 85             throw new UndeclaredThrowableException(t);
 86         }
 87     }
 88     
 89     static {
 90         try {
 91             $Proxy0.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
 92             $Proxy0.m4 = Class.forName("com.wjc.proxy.People").getMethod("getSex", (Class<?>[])new Class[0]);
 93             $Proxy0.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class<?>[])new Class[0]);
 94             $Proxy0.m3 = Class.forName("com.wjc.proxy.People").getMethod("getStandardsOfChoosingSpouse", (Class<?>[])new Class[0]);
 95             $Proxy0.m5 = Class.forName("com.wjc.proxy.People").getMethod("getHeight", (Class<?>[])new Class[0]);
 96             $Proxy0.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class<?>[])new Class[0]);
 97         }
 98         catch (NoSuchMethodException ex) {
 99             throw new NoSuchMethodError(ex.getMessage());
100         }
101         catch (ClassNotFoundException ex2) {
102             throw new NoClassDefFoundError(ex2.getMessage());
103         }
104     }
105 }

 

 

 

 

 

 

  

posted @ 2019-03-18 22:19  wujc_sh  阅读(615)  评论(0编辑  收藏  举报