推荐博客:代理模式原理及实例讲解
(1)代理模式:
(1) 代理模式是使用代理对象完成用户请求,屏蔽用户对真实对象的访问。
比如:现实世界的代理人被授权执行当事人的一些事宜,无需当事人出面,从第三方的额角度看,似乎当事人并不存在,因为他只和代理人通信。而事实上,代理人要有当事人授权并且在核心问题上请示当事人。
(2)在软件设计中:使用代理模式的意图也很多,比如
- 因为安全原因需要屏蔽客户端直接访问真实对象;
- 在远程调用中需要使用代理类处理远程方法调用技术细节,
- 为了提高系统性能,对真实对象进行封装,从而达到延迟加载的目的;
(2)代理模式角色划分:
-
主题接口:定义代理类和真实主题的公共对外方法,也是代理类代理真实主题的方法;
-
真实主题:真正实现业务逻辑的类;
-
代理类:用来代理和封装真实主题;
-
Main:客户端,使用代理类和主题接口完成一些工作。
(3)分类:
1,静态代理:
静态代理的实现模式一般是:首先创建一个接口(JDK代理都是面向接口的),然后创建具体实现类来实现这个接口,然后再创建一个代理类同样实现这个接口,不同之处在于,具体实现类的方法中需要将接口中定义的方法的业务逻辑功能实现,而代理类中的方法只要调用具体类中的对应方法即可,这样我们在需要使用接口中的某个方法的功能时直接调用代理类的方法即可,将具体的实现类隐藏在底层。
我的理解:由于Cinema(代理类)是事先编写、编译好的,而不是在程序运行过程中动态生成的,因此这个例子是一个静态代理的应用。
2,动态代理:
动态代理可以在程序运行期间根据需要动态的创建代理类及其实例来完成具体的功能
(4)总结
一个典型的动态代理创建对象过程可分为以下四个步骤:
1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...);
2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});
3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。
生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))
美中不足
诚然,Proxy已经设计得非常优美,但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持interface代理的问题,因为它的设计注定了这个遗憾。回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫Proxy。Java的继承机制注定了这些动态代理类们无法实现对class的动态代理,原因是多继承在Java中本质上就行不通。有很多条理由,人们可以否定对 class代理的必要性,但是同样有一些理由,相信支持class动态代理会更美好。接口和类的划分,本就不是很明显,只是到了Java中才变得如此的细化。如果只从方法的声明及是否被定义来考量,有一种两者的混合体,它的名字叫抽象类。实现对抽象类的动态代理,相信也有其内在的价值。此外,还有一些历史遗留的类,它们将因为没有实现任何接口而从此与动态代理永世无缘。如此种种,不得不说是一个小小的遗憾。但是,不完美并不等于不伟大,伟大是一种本质,Java动态代理就是佐例。