动机
在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给使用者、或者系统结构带来很多麻烦。如何在不是去透明操作对象的同时来管理/控制这些对象特有的复杂性?增加一层间接层是软件开发中常见的解决方式。定义
为其他对象提供一种代理以控制(隔离,使用接口)对这个对象的访问。总结
- “增加一层间接层”是软件系统中对许多复杂问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来许多问题,作为间接层的proxy对象便是解决这一问题的常用手段。
- 具体proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象做细粒度的控制,如copy-on-write技术,有些对象可能对组件模块提供抽象代理层,在架构层次对对象做proxy。
- Proxy 并不一定要求保持接口完整的一致性,只要能够实现间接控制,有时候损及一些透明性是可以接受的。
Java 动态代理机制
- 静态代理模式
以下代码基本符合顶部设计模式类图的内容,静态代理类使得在委托类内部变化的情况下,Client无需关注,同时在代理类可以实现自定义的修改(过滤判断,权限控制等)无需修改委托类。1
2
3
4
5
6
7
8
9
10public interface ISubject {
String request();
}
class RealSubject implements ISubject{
.lang.Override
public String request() {
return "hello world!";
}
}1
2
3
4
5
6
7
8
9
10
11
12class SubStaticProxy implements ISubject{
private RealSubject reaSubject;
public SubStaticProxy(RealSubject reaSubject) {
this.reaSubject = reaSubject;
}
public String request() {
return "before request.\n"+reaSubject.request()+"\nAfter request.";
}
}
但是,如果需要代理多个接口就需要提供对应的代理类,或者修改代理类的代码(一个代理类代理多个接口),如何让代理类在委托类数量增加的情况下固定不变?
- 动态代理
下面的代码实现了动态代理,Client可以根据需要绑定不同的委托类,系统将会自动根据绑定的委托类动态生成代理类。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class SubDynamicProxy implements InvocationHandler {
private Object realObject;
public Object bind(Object realObject) {
this.realObject = realObject;
return Proxy.newProxyInstance(
realObject.getClass().getClassLoader(),
realObject.getClass().getInterfaces(),
this
);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("addition process.");
return method.invoke(realObject, args);
}
}
1 | class Client{ |
代理类是如何生成,又是如何调用 Override 的invoke
函数的:
设置属性sun.misc.ProxyGenerator.saveGeneratedFiles
为true
可以在运行时看到生成的代理类 $Proxy0.class
.
查看newProxyInstance
的源码,下面是关键部分:
1 | // 复制接口 |
getProxyClass0()
最终调用ProxyGenerator中的generateClassFile()
函数实现class文件的生成:
- 调用
generateMethod()
添加equal、toString、hashCode这样的默认方法; - 循环获取每个接口内的每个方法,调用
generateMethod()
添加到代理类。 cons.newInstance(new Object[]{h})
分为两个过程,括号内部就是SubDynamicProxy
,也就是newProxyInstance
时传入的this
;生成类的父类就是Proxy
,Proxy
在构造函数设置了h
属性为构造传入的参数。generateMethod()
向方法中注入了(String)super.h.invoke(this, method, (Object[])args);
这里的 method 是m3 = Class.forName("ISubject").getMethod("request")
,结合上一步,我们发现都调用到了SubDynamicProxy
的invoke
方法。在这里做完额外的处理之后再执行委托类的对应方法。最终类之间的依赖关系如下图所示。
赏
使用支付宝打赏
使用微信打赏
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章