zoukankan      html  css  js  c++  java
  • 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 }

      

  • 相关阅读:
    201521123115《Java程序设计》第7周学习总结
    201521123115《Java程序设计》第6周学习总结
    201521123115 《Java程序设计》第5周学习总结
    201521123115 《Java程序设计》第4周学习总结
    201521123115 《Java程序设计》第3周学习总结
    201521123115《Java程序设计》第2周学习总结
    201521123114 《Java程序设计》第13周学习总结
    201521123114 《Java程序设计》第12周学习总结
    201521123114 《Java程序设计》第11周学习总结
    201521123114 《Java程序设计》第10周学习总结
  • 原文地址:https://www.cnblogs.com/wujc/p/10554933.html
Copyright © 2011-2022 走看看