首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

java署理模式以及动态代理详解

2012-12-20 
java代理模式以及动态代理详解本文讲述代理模式...代理模式的作用是:为其他对象提供一种代理以控制对这个

java代理模式以及动态代理详解

本文讲述代理模式...

代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。
在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

?

代理模式一般涉及到的角色有:
  抽象角色:声明真实对象和代理对象的共同接口;
  代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替

真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装;
  真实角色:代理角色所代表的真实对象,是我们最终要引用的对象;

?

下面四个类讲述一个简单的静态代理,参见程序Subject.java,RealSubject.java,ProxySubject.java和Client.java。把他们放在一个包下即可

,代码如下:

Subject.java代码
abstract public class Subject{?????
?????????
??? abstract public void request();?????
}??

?

Realsubject.java代码
public class RealSubject extends Subject?????
{?????
??? public void request()?????
??? {?????
??????? System.out.println("From real subject.");?????
??? }?????
}?


Proxysubject.java代码
public class ProxySubject extends Subject{?????
?????????
??? private RealSubject realSubject; // 以真实角色作为代理角色的属性?????
????
??? public void request() // 该方法封装了真实对象的request方法?????
??? {?????
??????? preRequest();?????
????
??????? if (realSubject == null) {?????
??????????? realSubject = new RealSubject();?????
??????? }?????
????
??????? realSubject.request(); // 此处执行真实对象的request方法?????
????
??????? postRequest();?????
??? }?????
????
??? private void preRequest() {?????
????
??????? System.out.println("先前做的事情");?????
??? }?????
????
??? private void postRequest() {?????
????
??????? System.out.println("之后做的事情");?????
??? }?????
}?

?

Client.java代码
public class Client{?????
??? public static void main(String[] args)?????
??? {?????
??????? Subject sub = new ProxySubject();?????
????
??????? sub.request();?????
??? }?????
}?


要有四个角色:抽象角色,代理角色,真实角色和客户。在Java中要想对其他对象引用,生成一个那个对象的属性就行了。比如本例中就是在

ProxySubject类中声明了RealSubject类的对象,作为一个属性存在ProxySubject中。

?

由以上代码可以看出,客户实际需要调用的是RealSubject类的request()方法,现在用ProxySubject来代理 RealSubject类,同样达到目的,同时还

封装了其他方法(preRequest(),postRequest()),可以处理一些其他问题。
?
另外,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色

必须对应一个 代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代

理类来解决。

?

下面讲述动态代理。

?

Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类(接口算作特殊类):


(1)Interface InvocationHandler:该接口中仅定义了一个方法

?

public 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,由它接管实际的工作。

?

下面例子讲述了一个动态代理Subject.java,RealSubject.java,DynamicSubject.java和Client.java,把他们放在一个包下,代码如下:

Subject.java代码
//抽象角色(之前是抽象类,此处应改为接口)?????
public interface Subject?????
{?????
??? public void request();?????
}?

?

Realsubject.java代码
//具体角色?????
public class RealSubject implements Subject?????
{?????
????
??? public RealSubject()?????
??? {?????
??? }?????
????
??? public void request()?????
??? {?????
??????? System.out.println("真正做事的。");?????
??? }?????
}?

?

Dynamicsubject.java代码
//代理处理器?????
/**????
?* 该代理类的内部属性为Object类,实际使用时通过该类的构造函数DynamicSubject(Object obj)对其赋值;????
?* 此外,在该类还实现了invoke方法,该方法中的 method.invoke(sub,args);????
?* 其实就是调用被代理对象的将要被执行的方法,方法参数sub是实际的被代理对象,????
?* args为执行被代理对象相应操作所需的参数。????
?* 通过动态代理类,我们可以在调用之前或之后执行一些相关操作????
?*/????
????
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("调用前" + method);?????
????
??????? method.invoke(sub, args);?????
????
??????? System.out.println("调用后 " + method);?????
????
??????? return null;?????
??? }?????
}??

?

Client.java代码
//客户端?????
public class Client?????
{?????
??? static public void main(String[] args) throws Throwable?????
??? {?????
????
??????? RealSubject rs = new RealSubject(); // 在这里指定被代理类?????
??????? InvocationHandler ds = new DynamicSubject(rs);?????
??????? Class<?> cls = rs.getClass();?????
????
??????? // 以下是一次性生成代理?????
????
??????? Subject subject = (Subject) Proxy.newProxyInstance(?????
??????????????? cls.getClassLoader(), cls.getInterfaces(), ds);?????
????
??????? subject.request();?????
??? }?????
}?

?

这个程序中把静态代理类的抽象类改变为一个接口,而实际类实现这个接口。是因为Proxy类的newProxyInstance方法传入需要提供一个接口,这个是

Java动态代理框架给我们设计好的了。本例的ProxySubject类实现了InvocationHandler接口及实现invoke方法,并且提供一个带参数的构造方法,

通过Client类动态的调用真实类。

?

?Client类通过DynamicSubject类生成真实类的代理对象,并经由Proxy类的newProxyInstance方法实现生成“一个能做真实类做的事的代理”,并由

该代理直接调用真实类所具有的方法。

?

?OK,也许还会有些迷惑,不过不要紧,没有什么高端的知识能够一次就成功的,要勤于练习。

?

下面这个类作为参考,代码如下:

Vectorproxy.java代码
import java.lang.reflect.InvocationHandler;?????
import java.lang.reflect.Method;?????
import java.lang.reflect.Proxy;?????
import java.util.List;?????
import java.util.Vector;?????
????
public class VectorProxy implements InvocationHandler?????
{?????
??? private Object proxyobj;?????
????
??? public VectorProxy(Object obj)?????
??? {?????
??????? proxyobj = obj;?????
??? }?????
????
??? public static Object factory(Object obj)?????
??? {?????
??????? Class<?> cls = obj.getClass();?????
????
??????? return Proxy.newProxyInstance(cls.getClassLoader(),?????
??????????????? cls.getInterfaces(), new VectorProxy(obj));?????
??? }?????
????
??? public Object invoke(Object proxy, Method method, Object[] args)?????
??????????? throws Throwable?????
??? {?????
??????? System.out.println("before calling " + method);?????
????
??????? if (args != null)?????
??????? {?????
??????????? for (int i = 0; i < args.length; i++)?????
??????????? {?????
??????????????? System.out.println(args[i] + "");?????
??????????? }?????
??????? }?????
??????? Object object = method.invoke(proxyobj, args);?????
????
??????? System.out.println("after calling " + method);?????
??????? return object;?????
??? }?????
????
??? @SuppressWarnings("unchecked")?????
??? public static void main(String[] args)?????
??? {?????
??????? List<String> v = (List<String>) factory(new Vector<String>(10));?????
????
??????? v.add("New");?????
??????? v.add("York");?????
??????? System.out.println(v);?????
????
??????? v.remove(0);?????
??????? System.out.println(v);?????
??? }?????
}?

import java.lang.reflect.InvocationHandler;??
import java.lang.reflect.Method;??
import java.lang.reflect.Proxy;??
import java.util.List;??
import java.util.Vector;??
?
public class VectorProxy implements InvocationHandler??
{??
??? private Object proxyobj;??
?
??? public VectorProxy(Object obj)??
??? {??
??????? proxyobj = obj;??
??? }??
?
??? public static Object factory(Object obj)??
??? {??
??????? Class<?> cls = obj.getClass();??
?
??????? return Proxy.newProxyInstance(cls.getClassLoader(),??
??????????????? cls.getInterfaces(), new VectorProxy(obj));??
??? }??
?
??? public Object invoke(Object proxy, Method method, Object[] args)??
??????????? throws Throwable??
??? {??
??????? System.out.println("before calling " + method);??
?
??????? if (args != null)??
??????? {??
??????????? for (int i = 0; i < args.length; i++)??
??????????? {??
??????????????? System.out.println(args[i] + "");??
??????????? }??
??????? }??
??????? Object object = method.invoke(proxyobj, args);??
?
??????? System.out.println("after calling " + method);??
??????? return object;??
??? }??
?
??? @SuppressWarnings("unchecked")??
??? public static void main(String[] args)??
??? {??
??????? List<String> v = (List<String>) factory(new Vector<String>(10));??
?
??????? v.add("New");??
??????? v.add("York");??
??????? System.out.println(v);??
?
??????? v.remove(0);??
??????? System.out.println(v);??
??? }??
}

这个类看不明白不要紧,慢慢来。

?

下面也是一个演示程序,作为扩展知识用,一共五个类,在同一包下,代码如下:

?

?五个类Foo.java, FooImpl.java, FooImpl2.java, CommonInvocationHandler.java和Demo.java。

Foo.java代码
public interface Foo?????
{?????
??? void doAction();?????
}??

public interface Foo??
{??
??? void doAction();??
}?

Fooimpl.java代码
public class FooImpl implements Foo?????
{?????
??? public FooImpl()?????
??? {?????
??? }?????
????
??? public void doAction()?????
??? {?????
??????? System.out.println("in FooImp1.doAction()");?????
??? }?????
}??

public class FooImpl implements Foo??
{??
??? public FooImpl()??
??? {??
??? }??
?
??? public void doAction()??
??? {??
??????? System.out.println("in FooImp1.doAction()");??
??? }??
}?

Fooimpl2.java代码
public class FooImpl2 implements Foo?????
{?????
??? public FooImpl2()?????
??? {?????
??? }?????
????
??? public void doAction()?????
??? {?????
??????? System.out.println("in FooImp2.doAction()");?????
??? }?????
}?

public class FooImpl2 implements Foo??
{??
??? public FooImpl2()??
??? {??
??? }??
?
??? public void doAction()??
??? {??
??????? System.out.println("in FooImp2.doAction()");??
??? }??
}

Commoninvocationhandler.java代码
import java.lang.reflect.InvocationHandler;?????
import java.lang.reflect.Method;?????
????
public class CommonInvocationHandler implements InvocationHandler?????
{?????
????
??? // 动态执行对象,需要回调的对象?????
??? private Object target;?????
????
??? // 支持构造子注射?????
??? public CommonInvocationHandler()?????
??? {?????
????
??? }?????
????
??? // 支持构造子注射?????
??? public CommonInvocationHandler(Object target)?????
??? {?????
??????? setTarget(target);?????
??? }?????
????
??? /**????
???? *?????
???? * 采用setter方法注射????
???? *?????
???? * @param target????
???? *?????
???? */????
??? public void setTarget(Object target)?????
??? {?????
??????? this.target = target;?????
??? }?????
????
??? /**????
???? *?????
???? * 调用proxy中指定的方法method,并传入参数列表args????
???? *?????
???? * @param proxy????
???? *??????????? 代理类的类型,例如定义对应method的代理接口????
???? *?????
???? * @param method????
???? *??????????? 被代理的方法????
???? *?????
???? * @param args????
???? *??????????? 调用被代理方法的参数????
???? *?????
???? * @return????
???? *?????
???? * @throws java.lang.Throwable????
???? *?????
???? */????
??? public Object invoke(Object proxy, Method method, Object[] args) throws Throwable?????
??? {?????
??????? return method.invoke(target, args);?????
??? }?????
}?

import java.lang.reflect.InvocationHandler;??
import java.lang.reflect.Method;??
?
public class CommonInvocationHandler implements InvocationHandler??
{??
?
??? // 动态执行对象,需要回调的对象??
??? private Object target;??
?
??? // 支持构造子注射??
??? public CommonInvocationHandler()??
??? {??
?
??? }??
?
??? // 支持构造子注射??
??? public CommonInvocationHandler(Object target)??
??? {??
??????? setTarget(target);??
??? }??
?
??? /**?
???? *??
???? * 采用setter方法注射?
???? *??
???? * @param target?
???? *??
???? */?
??? public void setTarget(Object target)??
??? {??
??????? this.target = target;??
??? }??
?
??? /**?
???? *??
???? * 调用proxy中指定的方法method,并传入参数列表args?
???? *??
???? * @param proxy?
???? *??????????? 代理类的类型,例如定义对应method的代理接口?
???? *??
???? * @param method?
???? *??????????? 被代理的方法?
???? *??
???? * @param args?
???? *??????????? 调用被代理方法的参数?
???? *??
???? * @return?
???? *??
???? * @throws java.lang.Throwable?
???? *??
???? */?
??? public Object invoke(Object proxy, Method method, Object[] args) throws Throwable??
??? {??
??????? return method.invoke(target, args);??
??? }??
}

Demo.java代码
import java.lang.reflect.Proxy;?????
????
public class Demo?????
{?????
??? public static void main(String[] args)?????
??? {?????
????
??????? // 1.通用的动态代理实现?????
????
??????? CommonInvocationHandler handler = new CommonInvocationHandler();?????
????
??????? Foo f;?????
????
??????? // 2.接口实现1?????
????
??????? handler.setTarget(new FooImpl());?????
????
??????? // 方法参数说明:代理类、代理类实现的接口列表、代理类的处理器?????
????
??????? // 关联代理类、代理类中接口方法、处理器,当代理类中接口方法被调用时,会自动分发到处理器的invoke方法?????
????
??????? // 如果代理类没有实现指定接口列表,会抛出非法参数异常?????
????
??????? f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),?????
????
??????? new Class[] { Foo.class },?????
????
??????? handler);?????
????
??????? f.doAction();?????
????
??????? // 3.接口实现2?????
????
??????? handler.setTarget(new FooImpl2());?????
????
??????? f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),?????
????
??????? new Class[] { Foo.class },?????
????
??????? handler);?????
????
??????? f.doAction();?????
??? }?????
}?

热点排行