代理模式

  • 一,什么是代理模式?
  • 二,为什么要使用代理模式
  • 三,代理模式的三种创建方式
    • 1.静态代理
    • 2.动态代理
      • 1.基于jdk接口的动态代理
      • 2.基于cglib父类的动态代理
      • 3.兄弟关系 VS 父子关系
  • 四,总结

一,什么是代理模式?

给一个对象提供一种代理对象以控制对该对象的访问。
简单点理解:
目标对象:原对象,我们需要通过代理对象控制它的访问,扩展其功能。
代理对象:代理模式产生的对象,是原对象的替身,在原有基础上进行修改。
在不改变原对象代码的基础上对原对象的功能进行扩展
再简单点理解:
比如点外卖事件
你想吃麻辣烫,自己又不想去店里吃,所以你点外卖,此时的外卖小哥,可以看作为代理对象。而你又想在吃完麻辣烫后喝一杯珍珠奶茶,所以你又联系外卖小哥帮你去店里买一杯。这个过程可以理解为加的扩展功能。

二,为什么要使用代理模式

降低了系统的耦合度,扩展性好
可以起到保护目标对象的作用

三,代理模式的三种创建方式

例子:
顾客想要点一份鱼香肉丝,让外卖员送过来,并且想要帮忙带一份珍珠奶茶。
分析:
顾客:目标对象
外卖员:代理对象
点珍珠奶茶:扩展功能

1.静态代理

需要我们手写代理类。两种形式:

1.接口方式实现:让目标对象和代理对象都实现一个共同接口。那么这两个类就有了公共的方法,就可以在代理对象中实现对目标对象功能的扩展。
实现代码如下

OrderInterface接口:

public interface OrderInterface {public String order(String foodName);
}

customer类:

public class Customer implements OrderInterface{public String order(String foodName){return "已下单点了"+foodName;}}

DeliveryClerk类:

public class DeliveryClerk implements OrderInterface{//把原来的对象传入并保存到成员位置。也就是目标类对象private OrderInterface source;public DeliveryClerk(OrderInterface source) {this.source=source;}@Overridepublic String order(String foodName) {String result = source.order(foodName);System.out.println("已经接订单在送去的路上");return result+"买了一杯珍珠奶茶";}
}

测试类:

public class Test {public static void main(String[] args) {//1.创建顾客对象Customer customer = new Customer();//2.创建代理对象DeliveryClerk deliveryClerk = new DeliveryClerk(customer);//3.调用方法String result = deliveryClerk.order("鱼香肉丝盖饭");System.out.println(result);}
}

2.继承方式:让代理对象继承目标对象,那么代理对象就拥有目标对象的方法,同时又可以对其功能进行扩展。
实现代码如下

customer类:

public class Customer {public String order(String foodName){return "已下单点了"+foodName;}
}

DeliveryClerk类:

public class DeliveryClerk extends Customer{@Overridepublic String order(String foodName) {String result = super.order(foodName);System.out.println("已经接订单在送去的路上");return result+"买了一杯珍珠奶茶";}
}

静态代理维护依然复杂,一旦接口或父类发生改变,所有相关的类或接口就都得进行维护。

2.动态代理

是在内存中生成代理对象的一种技术
无需手写代理类,也不会存在代码编译的过程。运用在内存中生产代理类的技术在JVM的运行区造一个代理对象,只需对需要修改的部分进行编辑。

1.基于jdk接口的动态代理

实际上就是在内存中生产一个对象,该对象实现了指定的目标对象的所有接口,代理对象和目标对象是兄弟关系。
jdk自带动态代理技术,需要使用一个静态方法来创建代理对象,它需要目标对象必须实现接口,生产的代理对象和原对象都实现相同的接口。

编写流程

  1. 准备一个目标类对象,也就是顾客对象
  2. 使用jdk的API动态的生成代理对象
  3. 调用代理对象执行相应的方法

参数解释:

1.ClassLoader loader:

固定写法,指定目标类对象的类的加载器即可,用于加载目标类及其接口的字节码文件,通常使用目标类的字节码文件调用getClassLoader()方法可得到。

2.Class<?>[] interfaces:

固定写法,指定目标类的所以接口的字节码对象的数组,通常使用目标类的字节码文件调用getinterfaces()方法可得到。

3.InvocationHander h:

这个参数是一个接口,主要关注它里面的一个方法,它会在代理类调用方法时执行,也就是说,在代理类对象中调用的任何方法都会执行invoke()方法。所以在此方法中进行代码的扩展。

invoke()方法中参数的含义:

1.proxy:就是代理类对象的一个引用也就是Proxy.newProxyInstance()方法的返回值;此引用几乎不会用到。
2.method:对应的就是触发invoke执行的方法的Method对象。假如我们调用了Xxx方法,该方法触发了invoke执行,那么method就是Xxx方法对应的反射对象Method。
3.args:代理对象调用方法时传入的实际参数

OrderInterface接口:

public interface OrderInterface {public String order(String foodName);public void test1();public void test2();
}

Customer类:

public class Customer implements OrderInterface {public String order(String foodName){return "已下单点了"+foodName;}@Overridepublic void test1() {}@Overridepublic void test2() {}}

Test 类:

public class Test {public static void main(String[] args) {//1. 准备一个目标类对象,也就是顾客对象Customer customer = new Customer();//2. 使用jdk的API动态的生成代理对象OrderInterface deliveryClerk = (OrderInterface) Proxy.newProxyInstance(customer.getClass().getClassLoader(),customer.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if ("order".equals(method.getName())) {Object result = method.invoke(customer, args);System.out.println("已经接订单在送去的路上");return result + "买了一杯珍珠奶茶";} else {return method.invoke(customer, args);//使用method反射调用,在原对象中执行方法,并不改变逻辑,也就是说原封不动调用原来的逻辑}}});//3. 调用代理对象执行相应的方法String result=deliveryClerk.order("鱼香肉丝盖饭");System.out.println(result);}
}

2.基于cglib父类的动态代理

第三方cglib动态代理技术也是可以使用一个静态代理方法来创建代理对象,它不要求目标类实现接口,但是要求目标类不能是最终类,也就是说不能被final修饰。因为cglib是基于目标类生成该类的一个子类作为代理类,所以目标对象必须可以被继承。

基于父类的动态代理是在内存中生成一个对象,该对象继承了原对象,所以代理对象实际上就是原对象的子类。

编写流程

首先需要导包

  1. 准备一个目标类对象,也就是顾客对象
  2. 使用cjlib创建代理对象
  3. 调用代理对象执行相应的方法

参数解释:

1.Class type:

指定我们要代理的目标类的字节码对象,也就是指定目标类的类型。
1.callback:

也是一个接口,只是名称定义的作用。只是让别的接口去继承它,提供一个方法它会在合适的时候回来调用它。通常使用其子类
它的子类MethodInterceptor(方法拦截器)接口,其只有一个方法,叫做intercept()方法

intercept()方法中的参数:

1.proxy:就是代理类对象的一个引用也就是Enharcer.create()方法的返回值;此引用几乎不会用到。
2.method:对应的就是触发intercept执行的方法的Method对象。假如我们调用了Xxx方法,该方法触发了invoke执行,那么method就是Xxx方法对应的反射对象Method。
3.args:代理对象调用方法时传入的实际参数
4.methodProxy:方法的代理对象,一般不做处理,暂时忽略。

Customer类

public class Customer {public String order(String foodName){return "已下单点了"+foodName;}public void test1() {}public void test2() {}
}

Test类:

public class Test {public static void main(String[] args) {// 创建一个目标类对象,也就是顾客对象Customer customer = new Customer();// 使用CGLIB创建代理对象Customer deliveryClerk = (Customer) Enhancer.create(customer.getClass(), new MethodInterceptor() {@Overridepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {// 判断,如果是order方法,则增强if ("order".equals(method.getName())) {Object result = method.invoke(customer, args);System.out.println("已经接订单在送去的路上");return result + "买了一杯珍珠奶茶";} else {return method.invoke(customer, args);//使用method反射调用,在原对象中执行方法,并不改变逻辑,也就是说原封不动调用原来的逻辑}}});//3. 调用代理对象执行相应的方法String result=deliveryClerk.order("鱼香肉丝盖饭");System.out.println(result);}
}

3.兄弟关系 VS 父子关系

兄弟关系

并列关系,不能互相转换,包容性比较差,在spring框架中,如果配置jdk的动态代理方式,一定要用接口类型接收代理类。

父子关系

代理对象是可以用父类的引用接收的。

四,总结

1.代理模式在Java开发中是广泛应用的,特别是在框架中,底层原理经常设计到。
2.静态代理需要手写代码且维护,修改非常繁琐,会引入很多工作量。所以常用动态代理。
动态代理中
3.在spring框架中默认支持了两种动态代理。如果指定的目标类实现了接口,spring中就会自动用jdk动态代理,如果没有实现接口就会自动用cglib方式。
4.我们在开发时,由于基于jdk的动态代理要求比较多,更不容易实现。所以很多人配置使用cglib动态代理。
5.如果使用dubbo+zookeeper,底层进行代理时最好配置使用cglib的方式进行代理。

设计模式——代理模式详解(Java版)相关推荐

  1. 软件设计模式——代理模式详解

    摘要 动态代理是Java语言中非常经典的一种设计模式,也是所有设计模式中最难理解的一种.那什么是代理设计模式?代理设计的基础概念就是通过代理控制对象的访问,可以在这个对象调用方法之前.调用方法之后去处 ...

  2. C++设计模式 - 代理模式详解一

    代理模式:提供一种可以对真实对象的访问对象,隐藏真实的对象,去除真实对象的非必要的职责. 大家都喜欢玩游戏,单机版游戏如红警.CS.暗黑了等(不小心就暴露了年龄),网络游戏如传奇.魔兽以及吃鸡游戏.王 ...

  3. cglib动态代理jar包_代理模式详解:静态代理+JDK/CGLIB 动态代理实战

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

  4. 代理模式详解(静态代理和动态代理的区别以及联系)

    原文链接:https://www.cnblogs.com/takumicx/p/9285230.html 1. 前言 代理模式可以说是生活中处处可见.比如说在携程上定火车票,携程在这里就起到了一个代理 ...

  5. 设计模式——状态模式详解

    0. 前言 写在最前面,本人的设计模式类博文,建议先看博文前半部分的理论介绍,再看后半部分的实例分析,最后再返回来复习一遍理论介绍,这时候你就会发现我在重点处标红的用心,对于帮助你理解设计模式有奇效哦 ...

  6. grpc java_grpc详解 java版

    grpc 详解 java版 Java中gRPC的基本教程介绍. 本教程提供了有关使用gRPC的基本Java程序员介绍. 通过遍历此示例,您将学习如何: grpc设计的核心概念. 在.proto文件中定 ...

  7. Java设计模式-模板方法模式详解

    Java设计模式-模板方法模式 文章目录 Java设计模式-模板方法模式 0.前言 1.模板方法原理 2.模板方法模式中的角色 3.模板方法模式的UML类图 4.代码实现 5.编码测试 6.模板模式中 ...

  8. java设计模式之代理模式详解

    代理模式在Java中十分常见,有如Spring实现AOP而使用动态代理,更有RPC实现中使用的调用端调用的代理服务.代理模型除了是一种设计模式之外,它更是一种思维,所以探讨并深入理解这种模型是非常有必 ...

  9. 代理模式详解--潘金莲版

    1,什么是代理模式? 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问. 2,策略模式有什么好处? 在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象 ...

  10. Spring AOP理论 +代理模式详解

    目录 1.理解AOP 1.1.什么是AOP 1.2.AOP体系与概念 1.3.Spring AOP 通知的执行顺序 2.代理模式 2.1.静态代理 2.2.静态代理的缺点 3.动态代理 JDK 动态代 ...

最新文章

  1. php session 在线用户,php – 使用$_SESSION超全局获取当前在线用户并将其重新设置回当前会话数据是否很难?...
  2. 输入3个字符串,按由小到大顺序输出
  3. 剧本杀,继狼人杀之后的下一个风口
  4. 删除矩阵中的任意一列元素
  5. 逻辑门电路的知识点归纳
  6. LeetCode 538. 把二叉搜索树转换为累加树
  7. 你应该需要知道的前端小技巧
  8. 电脑画画软件_数码印花设计与电脑手绘
  9. mysql数据库表分区_MySQL数据库之MySQL的分区和分表详解
  10. java中sam接口_具有非SAM接口的lambda的Java习惯用法
  11. tcpdump显示udp包_TCPdump抓包命令详解
  12. 使用procexp.exe查看线程
  13. mysql中drop语法错误_MySQL DROP TABLE操作以及 DROP 大表时的注意事项
  14. 一篇文章学会ICP许可证如何年检
  15. 电脑管家修复DNS服务器,DNS是什么?dns劫持是怎么回事?怎么处理?
  16. 学习虚幻4(一)U3D与UE4的比较
  17. SQL——行转列,列转行
  18. 经济危机与金融危机的学术解释与通俗到庸俗的解释,包你明白
  19. 计算机职称照图片,全国职称计算机报名如何上传照片。怎么提示你无需上传照片。可以直接进行报名呢...
  20. qduoj 生化危机ycb老师的电脑中毒了(邻接表)

热门文章

  1. pvbox3直播频道服务器维护,新一轮大服务器实装公告:3月12日凌晨维护
  2. ThinkPHP 的 Vender的简单实用
  3. 连续8个季度增长超100% 阿里云成长为“亚洲巨象”
  4. Olly's Shadow
  5. clickhouse分布式集群遇到的一些错误处理
  6. sql语句date函数
  7. 能同时模拟键盘及鼠标的神器--51单片机可控制
  8. 基于vue的时间轴轮播图插件 timeline-carousel
  9. proxyconnect tcp: dial tcp: lookup proxy.example.com on 8.8.8.8:53: no such host
  10. 童星养成系统的文推荐_戏骨、童星、实力派,《隐秘的角落》全员数据图鉴