摘要:静态代理在代理模式中,通常指的时静态代理。为实际类的接口,对应上面图中的,为接口的接口有一个方法需要自己实现,我们委托代理类实现的额外功能便放在该方法里。这就是动态代理相对于静态代理的意义。
代理模式是二十多种设计模式中的一个,属于比较常用的设计模式。本质上就是用来委托我们生成的代理类去完成一些额外的功能,这样能够达到解耦、封装的目的。
通常可以用在RPC、AOP中。比如在RPC中,当我们调用远程方法时,需要委托代理类帮助我们去通过网络连接远程的服务提供者,帮助我们将消息编码发送给服务端,帮我们接受服务端发来的结果。
在代理模式中,通常指的时静态代理。
这是静态代理的UML图。代理的思想是:代理类ProxySubject拥有实际类RealSubject的相同方法doSomething(实现相同的一个接口),同时代理类内聚了实际类(即传入实际类的一个引用),在代理类的doSomething方法中,通过实际类的引用调用实际类的doSomething方法,并在调用前后加入需要代理实现的额外功能。这样我们就可以通过调用代理类的相同方法来达到我们的目的。
举个例子:
interface Subject{ void doSomething(); }
class RealSubject implements Subject{ void doSomething(){ System.out.println("doSomething"); } }
class ProxySubject implements Subject{ private Subject target; public ProxySubject(Subject target){ this.target = target; } void doSomething(){ //do before System.out.println("do before"); target.doSomething();//调用realSubject的doSomething方法 //do after System.out.println("do after"); } }
class ProxyTest{ public static void main(String args[]){ //生成代理类,并将实际类传入 ProxySubject proxy = new ProxySubject(new RealSubject()); proxy.doSomething(); } }
以上,通过代理类执行实际类相同的方法,我们可以运行额外的功能。这里不仅会运行实际类doSomething方法里面的打印“doSomething”,还会在之前打印“do before",之后打印”do after",这两个即为额外的功能。
动态代理上面的静态代理其实存在一个问题,一个实际类对应一个代理类,而很多时候需要代理实现的额外功能是相同的,比如我们要在A类的某个方法调用前打印“before”,B类的某个方法调用前打印“before”,C类也有这个需求,如果用静态代理,我们需要写A类的代理,B类的代理,C类的代理。。。这样岂不是要累死。
java当中的动态代理就是为了这个解决这个问题。其实思路也很简单,不用去管A类、B类、C类还是什么其他类,统一用反射调用实际类的方法。
java提供了动态代理类Proxy,使用其中的静态方法Proxy.newProxyInstance(ClassLoader loader,Class>[] interfaces, InvocationHandler h)来动态生成代理类。interfaces为实际类的接口,对应上面图中的Subject,loader为接口的Classloader,InvocationHandler接口有一个invoke方法需要自己实现,我们委托代理类实现的额外功能便放在该方法里。需要注意的是由此看出java的动态代理需要有接口才能使用。如果不用接口实现动态代理只能求助于cglib这类字节码增强框架。
下面是动态代理的一般实现方法:
public class InvokeProxy implements InvocationHandler{ private Object target; public Object bind(Object target){ this.target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("do something before"); method.invoke(target, args); System.out.println("do something after"); return null; /* 如果反射调用的方法有返回值: Object result; result = method.invoke(target, args); return result; */ } }
同样有接口Subject:
interface Subject{ void doSomething(); }
假设类A实现了Subject接口,可以根据如下代码生成A的代理
public class ProxyTest { public static void main(String[] args) { Subject proxyA = (Subject)new InvokeProxy().bind(new A()); proxyA.doSomething(); } }
如果还有类B实现了Subject接口,我们只需更改上面的代码即可,而不用像静态代理那样重复的编写代码。这就是动态代理相对于静态代理的意义。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/65781.html
摘要:我们今天也来做一个万能遥控器设计模式适配器模式将一个类的接口转换成客户希望的另外一个接口。今天要介绍的仍然是创建型设计模式的一种建造者模式。设计模式的理论知识固然重要,但 计算机程序的思维逻辑 (54) - 剖析 Collections - 设计模式 上节我们提到,类 Collections 中大概有两类功能,第一类是对容器接口对象进行操作,第二类是返回一个容器接口对象,上节我们介绍了...
摘要:类的适配器结构目标角色这就是所期待得到的接口,由于是类适配器模式,因此目标不可以是类。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。和适配器模式的关系适配器模式的用意是改变所考虑对象的接口,而代理模式不能改变。 点击进入我的博客 3.1 适配器模式 适配器模式把一个类的接口变换成客户端所期待的另一种接口,使得原本因接口不匹配而无法在一起工作的两个类能够在一起工作。 3...
摘要:又是什么其实就是一种实现动态代理的技术,利用了开源包,先将代理对象类的文件加载进来,之后通过修改其字节码并且生成子类。 在实际研发中,Spring是我们经常会使用的框架,毕竟它们太火了,也因此Spring相关的知识点也是面试必问点,今天我们就大话Aop。特地在周末推文,因为该篇文章阅读起来还是比较轻松诙谐的,当然了,更主要的是周末的我也在充电学习,希望有追求的朋友们也尽量不要放过周末时...
阅读 561·2023-04-25 21:29
阅读 1090·2023-04-25 21:27
阅读 1029·2021-11-25 09:43
阅读 1052·2021-09-29 09:43
阅读 3596·2021-09-03 10:30
阅读 2833·2019-08-29 15:26
阅读 2780·2019-08-29 12:52
阅读 1725·2019-08-29 11:10