设计模式——代理模式详解(Java版)
代理模式
- 一,什么是代理模式?
- 二,为什么要使用代理模式
- 三,代理模式的三种创建方式
- 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自带动态代理技术,需要使用一个静态方法来创建代理对象,它需要目标对象必须实现接口,生产的代理对象和原对象都实现相同的接口。
编写流程
- 准备一个目标类对象,也就是顾客对象
- 使用jdk的API动态的生成代理对象
- 调用代理对象执行相应的方法
参数解释:
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是基于目标类生成该类的一个子类作为代理类,所以目标对象必须可以被继承。
基于父类的动态代理是在内存中生成一个对象,该对象继承了原对象,所以代理对象实际上就是原对象的子类。
编写流程
首先需要导包
- 准备一个目标类对象,也就是顾客对象
- 使用cjlib创建代理对象
- 调用代理对象执行相应的方法
参数解释:
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版)相关推荐
- 软件设计模式——代理模式详解
摘要 动态代理是Java语言中非常经典的一种设计模式,也是所有设计模式中最难理解的一种.那什么是代理设计模式?代理设计的基础概念就是通过代理控制对象的访问,可以在这个对象调用方法之前.调用方法之后去处 ...
- C++设计模式 - 代理模式详解一
代理模式:提供一种可以对真实对象的访问对象,隐藏真实的对象,去除真实对象的非必要的职责. 大家都喜欢玩游戏,单机版游戏如红警.CS.暗黑了等(不小心就暴露了年龄),网络游戏如传奇.魔兽以及吃鸡游戏.王 ...
- cglib动态代理jar包_代理模式详解:静态代理+JDK/CGLIB 动态代理实战
1. 代理模式 代理模式是一种比较好的理解的设计模式.简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标 ...
- 代理模式详解(静态代理和动态代理的区别以及联系)
原文链接:https://www.cnblogs.com/takumicx/p/9285230.html 1. 前言 代理模式可以说是生活中处处可见.比如说在携程上定火车票,携程在这里就起到了一个代理 ...
- 设计模式——状态模式详解
0. 前言 写在最前面,本人的设计模式类博文,建议先看博文前半部分的理论介绍,再看后半部分的实例分析,最后再返回来复习一遍理论介绍,这时候你就会发现我在重点处标红的用心,对于帮助你理解设计模式有奇效哦 ...
- grpc java_grpc详解 java版
grpc 详解 java版 Java中gRPC的基本教程介绍. 本教程提供了有关使用gRPC的基本Java程序员介绍. 通过遍历此示例,您将学习如何: grpc设计的核心概念. 在.proto文件中定 ...
- Java设计模式-模板方法模式详解
Java设计模式-模板方法模式 文章目录 Java设计模式-模板方法模式 0.前言 1.模板方法原理 2.模板方法模式中的角色 3.模板方法模式的UML类图 4.代码实现 5.编码测试 6.模板模式中 ...
- java设计模式之代理模式详解
代理模式在Java中十分常见,有如Spring实现AOP而使用动态代理,更有RPC实现中使用的调用端调用的代理服务.代理模型除了是一种设计模式之外,它更是一种思维,所以探讨并深入理解这种模型是非常有必 ...
- 代理模式详解--潘金莲版
1,什么是代理模式? 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问. 2,策略模式有什么好处? 在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象 ...
- Spring AOP理论 +代理模式详解
目录 1.理解AOP 1.1.什么是AOP 1.2.AOP体系与概念 1.3.Spring AOP 通知的执行顺序 2.代理模式 2.1.静态代理 2.2.静态代理的缺点 3.动态代理 JDK 动态代 ...
最新文章
- php session 在线用户,php – 使用$_SESSION超全局获取当前在线用户并将其重新设置回当前会话数据是否很难?...
- 输入3个字符串,按由小到大顺序输出
- 剧本杀,继狼人杀之后的下一个风口
- 删除矩阵中的任意一列元素
- 逻辑门电路的知识点归纳
- LeetCode 538. 把二叉搜索树转换为累加树
- 你应该需要知道的前端小技巧
- 电脑画画软件_数码印花设计与电脑手绘
- mysql数据库表分区_MySQL数据库之MySQL的分区和分表详解
- java中sam接口_具有非SAM接口的lambda的Java习惯用法
- tcpdump显示udp包_TCPdump抓包命令详解
- 使用procexp.exe查看线程
- mysql中drop语法错误_MySQL DROP TABLE操作以及 DROP 大表时的注意事项
- 一篇文章学会ICP许可证如何年检
- 电脑管家修复DNS服务器,DNS是什么?dns劫持是怎么回事?怎么处理?
- 学习虚幻4(一)U3D与UE4的比较
- SQL——行转列,列转行
- 经济危机与金融危机的学术解释与通俗到庸俗的解释,包你明白
- 计算机职称照图片,全国职称计算机报名如何上传照片。怎么提示你无需上传照片。可以直接进行报名呢...
- qduoj 生化危机ycb老师的电脑中毒了(邻接表)
热门文章
- pvbox3直播频道服务器维护,新一轮大服务器实装公告:3月12日凌晨维护
- ThinkPHP 的 Vender的简单实用
- 连续8个季度增长超100% 阿里云成长为“亚洲巨象”
- Olly's Shadow
- clickhouse分布式集群遇到的一些错误处理
- sql语句date函数
- 能同时模拟键盘及鼠标的神器--51单片机可控制
- 基于vue的时间轴轮播图插件 timeline-carousel
- proxyconnect tcp: dial tcp: lookup proxy.example.com on 8.8.8.8:53: no such host
- 童星养成系统的文推荐_戏骨、童星、实力派,《隐秘的角落》全员数据图鉴