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 }

      

  • 相关阅读:
    陶瓷电容的结构、工艺、失效模式
    Vue.js最佳实践
    Vue 超快速学习
    CSS 小技巧
    HTML5 Canvas
    webkit下面的CSS设置滚动条
    Some untracked working tree files would be overwritten by checkout. Please move or remove them before you can checkout. View them
    JSCS: Please specify path to 'JSCS' package
    React中ref的使用方法
    React 60S倒计时
  • 原文地址:https://www.cnblogs.com/wujc/p/10554933.html
Copyright © 2011-2022 走看看