代理模式:为其他对象提供一种代理以控制某个对象的访问。用在:在某些情况下,一个客户不想或者不能直接访问另一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用,代理对象还可以完成它附加的操作。

例子:就像房东、租客、中介的关系。中介(代理对象)为房东(真实对象)出租房子,租客(客户)通过中介(代理对象)来找房子租房子,中介完成了租房以后可以收取中介费(附加操作)。

先看看静态代理模式,通过上面对代理模式的理解,可以了解到代理模式:即不直接通过new一个真实对象来调用方法,而是通过代理对象来调用一个方法,所以代理对象包含真实对象的引用。下面看一下代码

接口:Subject包含一个方法

package com.example.designpattern.proxy;public interface Subject {void request();
}

RealSubject类,实现了Subject接口,为了简单起见,方法简单的输出一句话:

package com.example.designpattern.proxy;public class RealSubject implements Subject {//真是角色实现了public void request() {System.out.println("From real subject");}
}

代理类ProxySubject,也要实现Subject接口,实现Subject里面的方法,但是在这里里面是通过调用真实对象来实现的。

package com.example.designpattern.proxy;public class ProxySubject implements Subject {private RealSubject realSubject; //代理角色内部引用了真实角色//代理角色实现目标动作public void request() {this.preRequest(); //在真实角色操作之前所附加的操作if (realSubject == null){realSubject = new RealSubject();}realSubject.request(); // 真实角色所完成的事情this.afterRequet(); //在真实角色操作之后附加的操作}//代理角色之前完成的动作private void preRequest(){System.out.println("pre request");}//代理角色之后完成的动作private void afterRequet(){System.out.println("after request");}
}

客户调用者

package com.example.designpattern.proxy;public class Client {public static void main(String[] args) {ProxySubject proxy = new ProxySubject();//通过代理对象来调用方法proxy.request(); }
}

静态代理:
可以运行一下这些代码哦, 可以在Client类中看到,是通过代理ProxySubject的对象proxy来调用方法的,在代理类ProxySubject中,有一个真实对象的引用,在代理对象的中request()方法调用了真实对象的方法。这样的模式叫做代理模式。

优点是:

  1. 代理模式能将代理对象与真实对象被调用的目标对象分离。
  2. 一定程度上降低了系统的耦合度,扩展性好。

代理类中包含了对真实主题的引用,这样做也有缺点:

  1. 真实对象与代理类一一对应,增加真实类也要增加代理类,这样做会快速的增加类的数量,使得系统变得复杂。
  2. 设计代理以前真实主题必须事先存在,不太灵活。

采用动态代理可以解决以上问题,动态代理是相对于静态代理来说的。

可能你也会说怎么样实现动态创建实例,以前我们创建实例不都是通过new 的方式来实现的吗?

//如下
Hello hi = new Hello();

那么动态创建实例是由Java提供的功能,就不需要我们去new 对象,他已经定义好了静态方法Proxy.newProxyInstance(),只要传入参数调用就可以。Java文档里面有哦,如图:

Java标准库提供了一种动态代理(DynamicProxy)的机制:可以在运行期动态创建某个interface的实例。
参数解释:

Proxy.newProxyInstance(ClassLoader loader,    // 传入ClassLoaderClass<?>[] interfaces, // 传入要调用的接口的方法数组InvocationHandler h);  //传入InvocationHandler 的实例

下面看一下动态代理例子代码:
Subject 接口

package design.dynamicproxy;public interface Subject {void request(String str);
}

RealSubject类 实现 Subject 接口

package design.dynamicproxy;public class RealSubject implements Subject {@Overridepublic void request(String str) {System.out.println("From Real Subject!" + "  args:" + str );}
}

动态代理类DynamicSubject 实现了InvocationHandler,重写invoke()方法

package design.dynamicproxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/*** 该代理类的内部属性时Object类型,实际使用时,使用该类的构造方法传递一个对象* 此外该类还实现了invoke() 方法,该方法中的method.invoke() 其实就是要调用被代理对象的要执行的方法* 方法参数是object,表示该方法从属于object对象,通过动态代理类,我们可以在执行真是对象的* 方法前后可以加入一些额外的方法*/
public class DynamicSubject implements InvocationHandler {//引入的类型是Object的,可以随便传入任何一个对象private Object object;public DynamicSubject(Object object){this.object = object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("before calling:" + method);//等价于realSubject的request() 方法,如果这里不调用的话,不会调用Method 对象中的方法method.invoke(object, args);System.out.println("after calling:" + method);return null;}
}

Client类

package design.dynamicproxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;public class Client {public static void main(String[] args) {RealSubject realSubject = new RealSubject();InvocationHandler handler = new DynamicSubject(realSubject);Class<?> classType = handler.getClass();//下面的代码一次性生成代理// 动态生成了class com.sun.proxy.$Proxy0  的实例,Subject subject = (Subject) Proxy.newProxyInstance(classType.getClassLoader(), realSubject.getClass().getInterfaces(),handler);subject.request("eather");System.out.println(subject.getClass());  //输出class com.sun.proxy.$Proxy0,可以看到Proxy.newProxyInstance() 是系统自动生成的实例}
}

在Client中可以看到,我们这里调用方法的是 subject.request(“eather”); 这个对象subject 不是通过new DynamicSubject()生成的,而是Java内部写好的方法在运行时动态生成对象;可能有人说

InvocationHandler handler = new DynamicSubject(realSubject);

这里不是通过new new DynamicSubject(realSubject); 生成了一个对象吗? 是的,但是它是InvocationHandler 类型的,主要是传递一个InvocationHandler类型参数给Proxy.newProxyInstance(); 即最后一个参数。通过Client类的最后一句输出可以看到它是 class com.sun.proxy.$Proxy0 ,这是Java运行时生成的。

解决了静态代理的难题:1. 真实对象与代理类一一对应,增加真实类也要增加代理类,这样做会快速的增加类的数量,使得系统变得复杂。 为什么这么说呢, 因为代理类引用的类型是Object的,可以随便传入任何一个对象,当真实类增加时,代理类不用增加,new DynamicSubject(object); new的时候把要传入的对象传进去即可。

下面是Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h); 这个方法的源码啦,可以看看,深入了解一下

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException{Objects.requireNonNull(h);final Class<?>[] intfs = interfaces.clone();final SecurityManager sm = System.getSecurityManager();if (sm != null) {checkProxyAccess(Reflection.getCallerClass(), loader, intfs);}/** Look up or generate the designated proxy class.生成一个代理类对象*/Class<?> cl = getProxyClass0(loader, intfs);/** Invoke its constructor with the designated invocation handler.使用指定的调用处理程序调用其构造函数。就是使用InvocationHandler 实例调用【要调用方法的那个类】的构造方法*/try {if (sm != null) {checkNewProxyPermission(Reflection.getCallerClass(), cl);}final Constructor<?> cons = cl.getConstructor(constructorParams);final InvocationHandler ih = h;if (!Modifier.isPublic(cl.getModifiers())) {AccessController.doPrivileged(new PrivilegedAction<Void>() {public Void run() {cons.setAccessible(true);return null;}});}return cons.newInstance(new Object[]{h});} catch (IllegalAccessException|InstantiationException e) {throw new InternalError(e.toString(), e);} catch (InvocationTargetException e) {Throwable t = e.getCause();if (t instanceof RuntimeException) {throw (RuntimeException) t;} else {throw new InternalError(t.toString(), t);}} catch (NoSuchMethodException e) {throw new InternalError(e.toString(), e);}}

Java设计模式:(一)动态代理分析 (含静态代理)相关推荐

  1. Java代理设计模式(Proxy)的具体实现:静态代理和动态代理

    Java代理设计模式(Proxy)的具体实现:静态代理和动态代理 实现方式一:静态代理 静态代理方式的优点 静态代理方式的缺点 Java动态代理实现方式一:InvocationHandler Java ...

  2. 设计模式之代理模式(静态代理、Java动态代理、Cglib动态代理)

    代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问.这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介. 提醒:动态代理中涉及到以前的一些知识 ...

  3. 02.Java动态代理实现与原理分析之静态代理

    一.代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关 ...

  4. Java的代理模式之静态代理和动态代理

    文章目录 静态代理 动态代理 jdk生成代理对象 cglib代理 代理模式简介: 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目 ...

  5. 【Java】代理模式(静态代理动态代理)

    CONTENT 代理模式 静态代理 动态代理 JDK 动态代理(基于接口) CGLIB 动态代理(基于类继承) JDK 动态代理 v.s. CGLIB 动态代理 JDK 动态代理为什么必须基于接口 R ...

  6. Java设计模式-----Cglib动态代理(Cglib Proxy)

    接上文:4.2Java设计模式-----JDK动态代理(Dynamic Proxy) Cglib动态代理 百度百科:Cglib是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java ...

  7. Java之代理(jdk静态代理,jdk动态代理,cglib动态代理,aop,aspectj)

    Java之代理... 1 一.         概念... 1 二.         jdk的静态代理... 1 三.         jdk动态代理... 4 四.         cglib 动态 ...

  8. 代理详解 静态代理+JDK/CGLIB 动态代理实战

    1. 代理模式 代理模式是一种比较好理解的设计模式.简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对 ...

  9. JAVA设计模式理解与总结(下)代理模式适配器模式观察者模式

    码了好几年代码的打字机器我,对于设计模式这个词,肯定是一点也不陌生,但是对于设计模式的理解,因为日常开发中,增删改查较多,使用设计模式思想来优化代码的机会就很少.也不乏在翻阅源码的时候,叹服于别人优秀 ...

  10. 23种设计模式7_代理模式之一静态代理

    23种设计模式7_代理模式之一静态代理 1 基本介绍 代理模式:为其他对象提供一种代理以控制对这个对象的访问 代理模式也叫委托模式,它是一项基本设计技巧.许多其他的模式,如状态模式.策略模式.访问者模 ...

最新文章

  1. python学生管理系统-python实现学生成绩管理系统
  2. sql远程mysql服务器查询_sql server 使用链接服务器远程查询
  3. autojs定时可以选定日期吗_Excel工作表中的7个“一键完成”,你真的都了解、掌握吗?...
  4. NOTIFYICONDATA结构
  5. 【报错解决】linux网络编程报错storage size of ‘serv_addr’ isn’t known解决办法
  6. react 组件传值
  7. 【NIPS2020】 Workshop List
  8. 深拷贝与浅拷贝的区别
  9. HTMLElement对象
  10. Go程序:演示map用法
  11. Java定时任务工具详解之Timer篇
  12. property中的strong 、weak、copy 、assign 、retain 、unsaf
  13. paip.按键精灵调用其它程序及DLL以及EXE命令行的方法
  14. 计算机程序领域专利撰写,干货 | 计算机软件专利撰写模板
  15. Python编程 从入门到实践 第2版
  16. 学堂在线计算机通信网络,第二章 数据通信的基础知识 计算机网络笔记 学堂在线 2.4差错控制...
  17. 南开大学2019年数学分析考研试题
  18. 【牛客练习赛41 E.球的体积并】球的体积并模板
  19. 儿童手工制作日历_日历的手工制作教程图解
  20. bat 链接mysql数据库_使用bat脚本进行数据库操作

热门文章

  1. 安卓模拟器网页游戏连不上服务器,教大家夜神模拟器游戏无法联网的原因和解决方法...
  2. jeesite4打包部署到服务器
  3. 如何挑选一款优秀的企业网盘
  4. 47金山CEO张宏江:2013年移动医疗领域或有大爆发
  5. 直播页面6:直播中的弹幕_烈焰弹幕使
  6. 如何使用电视遥控器在Windows中控制Netflix
  7. 视频监控安防平台-GB28181_2016版-注册、心跳、注销
  8. matlab中电流调节器仿真模型,直流调速系统的matlab仿真(课程设计作业).docx
  9. 远力集团,到底是如何成为中国城市产业发展新引擎的?
  10. 动态规划——青蛙过桥