代理模式应该是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(); }

来个实现类

 package com.wjc.proxy;

 public class Wjc implements People {

     private String height = "170";
private String Sex = "男"; @Override
public String getHeight() {
// TODO Auto-generated method stub
return height;
} @Override
public String getSex() {
// TODO Auto-generated method stub
return Sex;
} @Override
public void getStandardsOfChoosingSpouse() {
// TODO Auto-generated method stub
System.out.println("性别男,爱好女");
System.out.println("不想努力了,求富婆包养"); } }

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

 package com.wjc.proxy;

 import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; public class MatchMaker implements InvocationHandler {
// 拿到被代理的对象
private People target; // 获取被代理对象
public Object getInstance(People target) throws Exception {
this.target = target;
Class clazz = target.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("-------这是一位"+this.target.getSex()+"性-------"); method.invoke(this.target, args);
System.out.println("找富婆是要付出代价的"); return null;
} }

测试一下

 package com.wjc.proxy;

 public class Test {
public static void main(String[] args) { try {
People instance = (People) new MatchMaker().getInstance(new Wjc());
instance.getStandardsOfChoosingSpouse(); instance.getHeight();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}

测试结果

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

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

 package com.wjc.proxy;

 public class Test2 {
public static void main(String[] args) { try {
Wjc wjc = new Wjc();
People instance = (People) new MatchMaker().getInstance(wjc);
System.out.println(wjc.getClass());
System.out.println(instance.getClass()); } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
}

执行结果

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

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

大致代理流程如下所示

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

  

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

打印类方法

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

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

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

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

 import com.wjc.proxy.*;
import java.lang.reflect.*; public final class $Proxy0 extends Proxy implements People
{
private static Method m1;
private static Method m4;
private static Method m2;
private static Method m3;
private static Method m5;
private static Method m0; public $Proxy0(final InvocationHandler invocationHandler) {
super(invocationHandler);
} public final boolean equals(final Object o) {
try {
return (boolean)super.h.invoke(this, $Proxy0.m1, new Object[] { o });
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
} public final String getSex() {
try {
return (String)super.h.invoke(this, $Proxy0.m4, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
} public final String toString() {
try {
return (String)super.h.invoke(this, $Proxy0.m2, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
} public final void getStandardsOfChoosingSpouse() {
try {
super.h.invoke(this, $Proxy0.m3, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
} public final String getHeight() {
try {
return (String)super.h.invoke(this, $Proxy0.m5, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
} public final int hashCode() {
try {
return (int)super.h.invoke(this, $Proxy0.m0, null);
}
catch (Error | RuntimeException error) {
throw;
}
catch (Throwable t) {
throw new UndeclaredThrowableException(t);
}
} static {
try {
$Proxy0.m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
$Proxy0.m4 = Class.forName("com.wjc.proxy.People").getMethod("getSex", (Class<?>[])new Class[0]);
$Proxy0.m2 = Class.forName("java.lang.Object").getMethod("toString", (Class<?>[])new Class[0]);
$Proxy0.m3 = Class.forName("com.wjc.proxy.People").getMethod("getStandardsOfChoosingSpouse", (Class<?>[])new Class[0]);
$Proxy0.m5 = Class.forName("com.wjc.proxy.People").getMethod("getHeight", (Class<?>[])new Class[0]);
$Proxy0.m0 = Class.forName("java.lang.Object").getMethod("hashCode", (Class<?>[])new Class[0]);
}
catch (NoSuchMethodException ex) {
throw new NoSuchMethodError(ex.getMessage());
}
catch (ClassNotFoundException ex2) {
throw new NoClassDefFoundError(ex2.getMessage());
}
}
}

  

spring设计模式_代理模式的更多相关文章

  1. Java 设计模式_代理模式(2016-08-19)

    概念: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 就是一个人或者机构代表另一个人或者机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一 ...

  2. Spring框架_代理模式(静态代理,动态代理,cglib代理)

    共性问题: 1. 服务器启动报错,什么原因? * jar包缺少.jar包冲突 1) 先检查项目中是否缺少jar包引用 2) 服务器: 检查jar包有没有发布到服务器下:                 ...

  3. Spring设计模式_工厂模式

    先说下工厂模式的特性 1.对于调用者来说,影藏了复杂的逻辑处理过程,调用者只关心执行结果. 2.工厂要对结果负责,保证生产出符合规范的产品. Git代码地址  https://github.com/w ...

  4. 设计模式_代理模式_在SqlSessionTemplate(Spring)中的应用

    1.SqlSessionTemplate的构造函数,根据传入的SqlSessionFactory和ExecutorType创建一个Spring管理的SqlSession,并生成SqlSession的动 ...

  5. Spring设计模式_策略模式/其他

    策略模式特性 1.执行最终结果一样 2.执行过程和执行逻辑不一样 3.使用同一接口 达到目的就可以了 Git地址 https://github.com/wujiachengSH/WjcStrategy ...

  6. 【GOF23设计模式】代理模式

    来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_代理模式.静态代理 package com.test.proxy.staticProxy; public interfac ...

  7. Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景

    我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...

  8. java设计模式6——代理模式

    java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代 ...

  9. C#设计模式(13)——代理模式(Proxy Pattern)

    一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访问到这些对象,如果直接访问对象给系统带来不必要的复杂性,这时候可以在客户端和目标对象之间增加一层中间层,让代 ...

随机推荐

  1. Android 实战美女拼图游戏 你能坚持到第几关

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40595385,本文出自:[张鸿洋的博客] 1.概述 继2048之后,今天给大家带 ...

  2. python读文件的三个方法read()、readline()、readlines()详解

    文件 runoob.txt 的内容如下: 1:www.runoob.com2:www.runoob.com3:www.runoob.com4:www.runoob.com5:www.runoob.co ...

  3. Go-技篇第二 命名规范

    优秀的命名 优秀的命名应当是一贯的.短小的.精确的.所谓一贯,就是说同一个意义在不同的环境下的命名应当一致,譬如依赖关系,不要在一个方法中命名为depend,另一个方法中命名为rely.所谓短小,不必 ...

  4. mfc启动画面

    目标 用一张位图来作为启动画面,在进入程序时显示. 策略 在应用程序类的I n i t I n s t a n c e ()函数中,在最早时刻创建启动窗口.启动窗口用一个位图类显示在普通窗口中. 步骤 ...

  5. 【转】AB实验设计思路及实验落地

    这篇文章会讨论: 在什么情况下需要做 AB 实验 从产品/交互角度,如何设计一个实验 前端工程师如何打点 如何统计数据,并保证数据准确可信 如何分析实验数据,有哪些数据需要重点关注 附:如何搭建前端实 ...

  6. 浏览器加载 CommonJS 模块的原理与实现

    就在这个周末,npm 超过了 cpan ,成为地球上最大的软件模块仓库. npm 的模块都是 JavaScript 语言写的,但浏览器用不了,因为不支持 CommonJS 格式.要想让浏览器用上这些模 ...

  7. C# winform 检测当前电脑安装的.net framework版本

    private static bool GetDotNetRelease(int release) { const string subkey = @"SOFTWARE\Microsoft\ ...

  8. sqlmap Bool型&延时型 检测策略分析

    目录 sqlmap Bool型&延时型 检测策略分析 0x00 预备-queryPage() 0x01 bool型检测策略 判断依据 quick_ratio() 案例 0x02 延时型 判断依 ...

  9. asp.net core系列 45 Web应用 模型绑定和验证

    一. 模型绑定 ASP.NET Core MVC 中的模型绑定,是将 HTTP 请求中的数据映射到action方法参数. 这些参数可能是简单类型的参数,如字符串.整数或浮点数,也可能是复杂类型的参数. ...

  10. clang如何获得程序控制流图

    在低版本的clag中,可以直接clang -cc1 -analyze -cfg-dump 1.c来获得程序控制流图,但较高版本后就不行了 另外clang -cc1默认仅限当前目录,所以会出现fata ...