1.
代理模式
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到的角色有:
抽象角色
:声明真实对象和代理对象的共同接口;
代理角色
:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色
:代理角色所代表的真实对象,是我们最终要引用的对象。(参见文献1)
以下以《
Java
与模式》中的示例为例:
抽象角色:
abstract public class Subject
{
abstract public void request();
}
真实角色:实现了
Subject
的
request()
方法。
public class RealSubject extends Subject
{
public RealSubject()
{
}
public void request()
{
System.out.println("From real subject.");
}
}
代理角色:
public class ProxySubject extends Subject
{
private RealSubject realSubject;
//
以真实角色作为代理角色的属性
public ProxySubject()
{
}
public void request()
//
该方法封装了真实对象的
request
方法
{
preRequest();
if( realSubject == null )
{
realSubject = new RealSubject();
}
realSubject.request();
//
此处执行真实对象的
request
方法
postRequest();
}
private void preRequest()
{
//something you want to do before requesting
}
private void postRequest()
{
//something you want to do after requesting
}
}
客户端调用:
Subject sub=new ProxySubject();
Sub.request();
由以上代码可以看出,客户实际需要调用的是
RealSubject
类的
request()
方法,现在用
ProxySubject
来代理
RealSubject
类,同样达到目的,同时还封装了其他方法
(preRequest(),postRequest())
,可以处理一些其他问题。
另外,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过
Java
的动态代理类来解决。
2.
动态代理类
Java
动态代理类位于
Java.lang.reflect
包下,一般主要涉及到以下两个类:
(1). Interface InvocationHandler
:该接口中仅定义了一个方法
Object
:
invoke(Object obj,Method method, Object
[] args)
。在实际使用时,第一个参数
obj
一般是指代理类,
method
是被代理的方法,如上例中的
request()
,
args
为该方法的参数数组。这个抽象方法在代理类中动态实现。
(2).Proxy
:该类即为动态代理类,作用类似于上例中的
ProxySubject
,其中主要包含以下内容:
Protected Proxy(InvocationHandler h)
:构造函数,估计用于给内部的
h
赋值。
Static Class getProxyClass (ClassLoader loader, Class[] interfaces)
:获得一个代理类,其中
loader
是类装载器,
interfaces
是真实类所拥有的全部接口的数组。
Static Object newProxyInstance
(ClassLoader loader, Class[] interfaces, InvocationHandler h)
:返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。
所谓Dynamic
Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些
interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic
Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。(参见文献3)
在使用动态代理类时,我们必须实现InvocationHandler接口,以第一节中的示例为例:
抽象角色
(之前是抽象类,此处应改为接口):
public interface Subject
{
abstract public void request();
}
具体角色
RealSubject
:同上;
代理角色:
import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
public class DynamicSubject implements InvocationHandler {
private Object sub;
public DynamicSubject() {
}
public DynamicSubject(Object obj) {
sub = obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before calling " + method);
method.invoke(sub,args);
System.out.println("after calling " + method);
return null;
}
}
该代理类的内部属性为
Object
类,实际使用时通过该类的构造函数
DynamicSubject(Object obj)
对其赋值;此外,在该类还实现了
invoke
方法,该方法中的
method.invoke(sub,args);
其实就是调用被代理对象的将要被执行的方法,方法参数
sub
是实际的被代理对象,
args
为执行被代理对象相应操作所需的参数。通过动态代理类,我们可以在调用之前或之后执行一些相关操作。
客户端
:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Client
{
static public void main(String[] args) throws Throwable
{
RealSubject rs = new RealSubject();
//
在这里指定被代理类
InvocationHandler ds = new DynamicSubject(rs);
//
初始化代理类
Class cls = rs.getClass();
//
以下是分解步骤
/*
Class c = Proxy.getProxyClass(cls.getClassLoader(),cls.getInterfaces()) ;
Constructor ct=c.getConstructor(new Class[]{InvocationHandler.class});
Subject subject =(Subject) ct.newInstance(new Object[]{ds});
*/
//
以下是一次性生成
Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(),
cls.getInterfaces(),ds );
subject.request();
}
通过这种方式,被代理的对象
(RealSubject)
可以在运行时动态改变,需要控制的接口
(Subject
接口
)
可以在运行时改变,控制的方式
(DynamicSubject
类
)
也可以动态改变,从而实现了非常灵活的动态代理关系(参见文献2)。
参考文献:
1.
阎宏,《J
ava
与模式》
2.
透明
,
《动态代理的前世今生》
3. Forest Hou,
《
Dynamic Proxy
在
Java RMI
中的应用》
版权声明:CSDN是本Blog托管服务提供商。如本文牵涉版权问题,CSDN不承担相关责任,请版权拥有者直接与文章作者联系解决。
分享到:
相关推荐
对代理模式与Java动态代理类的理解说明
1:静态代理出现的实际背景,静态代理时如何演化成动态代理 2: 动态代理demo 举例实际应用场景(载入数据库驱动的时候,使用AIDL与系统Servic...4: 动态代理使用到基础理论:Class.forName("xxxx") 得到Class类 。
代理模式java代码 Proxy(5) 2个代理类 开发宝典
Java代理模式模板代码,包含动态代理与静态代理。 静态代理使用了传统的代理类来代理,动态代理中使用了jdk的反射原理进行代理
在代理模式中,主要有两种类型:静态代理和动态代理。 1.静态代理: 静态代理是指在编译期间就已经确定代理类和被代理类的关系,需要手动编写代理类。代理类需要实现与被代理类相同的接口,并且在代理类中持有一个被...
详细而又简单的讲述了java动态代理设计模式
java设计模式【之】JDK动态代理...代理类,接收父亲类对象,利用反射机制,创建一个代理对象(在内存中动态创建代理对象) * Proxy.newProxyInstance (ClassLoader(类加载器),interface(接口),handler(监听处理器))
代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个...
java 设计模式 mvc模式 单例模式 代理 工厂 简单工厂
* 代理模式 * 在开发者的角度来看,创建一个代理对象,提供给用户使用,避免用户直接访问真正的对象 * 在用户角度来看,就是普通的类方法调用 * * 作用 * 1.保护被代理对象 * 2.增强被代理对象 * 3.完全...
该资源提供了三种代理模式的使用代码,其中包含每种模式的jar包、具体代码、Demo测试类,详细的注释帮助你来理解。
12.3.1 代理模式的优点 12.3.2 代理模式的应用 12.4 代理模式的扩展 12.4.1 普通代理 12.4.2 强制代理 12.4.3 代理是有个性的 12.4.4 虚拟代理 12.4.5 动态代理 12.5 最佳实践 第13章 原型模式 13.1 个性化电子账单 ...
关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理。 代理模式是常用的java设计模式,他的特征是代理类与委托类有...
2.结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。 4.行为型模式:模板方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略...
设计模式之代理模式Java实现和类设计图,包括静态代理和动态代理
文章目录一、代理模式定义二、代理模式的结构和说明三、代理模式的分类四、代理模式示例五、动态代理1、JDK动态代理JDK动态代理使用步骤JDK动态...动态代理注意事项六、三种代理方式的对比七、代理模式的应用场景及案例...
java三种代理模式的源码,包含泛型改写
代理模式(Proxy Pattern) 3 行为型模式 这些设计模式特别关注对象之间的通信。 责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式...
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、...
设计模式之代理模式,请求的链式处理——职责链模式,请求发送者与接收者解耦——命令模式,自定义语言的实现——解释器模式,遍历聚合对象中的元素——迭代器模式,协调多个对象之间的交互——中介者模式,撤销功能...