您的位置:首页 > 编程语言 > Java开发

如何使用Proxy模式及Java内建的动态代理机制

2010-03-03 15:22 1386 查看
1.Proxy

模式


代理模式支持将某些操作从实际的对象中分离出来,通过它的代理类提供处理。这样便于修改和管理这些特定的操作。

下面示例一个代理模式的实现。



<<interface>>Subject.java

package

com.zj.proxy;

public


interface

Subject {

void

operation1();

void

operation2(String arg);

}

现实类
RealSubject.java

package

com.zj.proxy;

public


class

RealSubject
implements

Subject {

public


void

operation1() {

System.
out

.println(
"Realer do operation1"
);

}

public


void

operation2(String arg) {

System.
out

.println(
"Realer do operation2 with "
+ arg);

}

}

代理类
ProxySubject.java

package

com.zj.proxy;

public


class

ProxySubject
implements

Subject {

private

Subject
proxied
;
//
被代理对象

public

ProxySubject(Subject
proxied) {

this

.
proxied
= proxied;

}

public


void

operation1() {

System.
out

.println(
"Proxyer do operation1"
);

proxied
.operation1();

}

public


void

operation2(String arg) {

System.
out

.println(
"Proxyer do operation2 with "
+ arg);

proxied
.operation2(arg);

}

}

测试类

SimpleProxyDemo.java

package

com.zj.proxy.client;

import

com.zj.proxy.Subject;

import

com.zj.proxy.RealSubject;

import

com.zj.proxy.ProxySubject;

public


class

SimpleProxyDemo {

public


static


void

consumer(
Subject

subject)
{

subject.operation1();

subject.operation2(
"ZJ"
);

}

public


static


void

main(String[] args) {

RealSubject real =
new

RealSubject();

System.
out

.println(
"===Without Proxy==="
);

consumer
(real);

System.
out

.println(
"===Use Proxy==="
);

consumer
(
new


ProxySubject(real));

}

}

结果:

===Without Proxy===

Realer do operation1

Realer do operation2 with ZJ

===Use Proxy===

Proxyer do operation1

Realer do operation1

Proxyer do operation2 with ZJ

Realer do operation2 with ZJ

2.

使用

Java

的动态代理机制


设计一个类用于实现
InvocationHandle
接口,
InvocationHandler
是代理实例的调用处理程序实现的接口。

每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的
invoke
方法。

<<interface>>InvocationHandle.java

package

java.lang.reflect;

public


interface

InvocationHandler {

public

Object invoke(Object proxy,
Method method, Object[] args)

throws

Throwable;

}

对应
invoke
参数:

[1]proxy -
在其上调用方法的代理实例;

[2]method -
对应于在代理实例上调用的接口方法的
Method
实例;

[3]args -
包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为
null


现在设计一个类实现该接口,并提供代理实例。

DynamicProxyHandler.java

package

com.zj.proxy.dynamic;

import

java.lang.reflect.InvocationHandler;

import

java.lang.reflect.Method;

public


class

DynamicProxyHandler
implements


InvocationHandler {

private

Object
proxied
;

public

DynamicProxyHandler(Object
proxied) {

this

.
proxied
= proxied;

}

public

Object invoke(Object proxy,
Method method, Object[] args)

throws

Throwable {

System.
out

.println(
"**** proxy: ****/n"
+
proxy.getClass()

+
"/nmethod: "
+ method +
"/nargs: "
+ args);

if

(args !=
null

)

for

(Object arg : args)

System.
out

.println(
"
"
+ arg);

return

method.invoke(
proxied
, args);

}

}

这里的
private

Object
proxied
;
即代理实例,也即上文代理模式中介绍的
RealSubject
对象。


invoke()
方法中,我们会打印它的所有参数,并调用当前代理的方法。

测试类

DynamicProxyDemo.java

package

com.zj.proxy.client;

import


java.lang.reflect.Proxy;

import

com.zj.proxy.Subject;

import

com.zj.proxy.RealSubject;

import


com.zj.proxy.dynamic.DynamicProxyHandler;

public


class

DynamicProxyDemo {

public


static


void

consumer(Subject subject) {

subject.operation1();

subject.operation2(
"ZJ"
);

}

public


static


void

main(String[] args) {

RealSubject
real =
new

RealSubject();

System.
out

.println(
"===Without Proxy==="
);

consumer
(real);

System.
out

.println(
"===Use Proxy==="
);

Subject proxy = (Subject) Proxy.newProxyInstance
(Subject.
class


.getClassLoader(),
new

Class[] {
Subject.
class

},

new

DynamicProxyHandler(real));

consumer
(proxy);

}

}

这里通过
Proxy
的静态方法
newProxyInstance(ClassLoader
loader, Class<?>[] interfaces,InvocationHandler h)
生成代理类,并传递与其关联的调用处理程序
new

DynamicProxyHandler(real)


对于
newProxyInstance()
的参数:

[1]loader -
定义代理类的类加载器


[2]interfaces -
代理类要实现的接口列表


[3]h -
指派方法调用的调用处理程序


测试结果:

===Without Proxy===

Realer do operation1

Realer do operation2 with ZJ

===Use Proxy===

**** proxy: ****

class $Proxy0

method: public abstract void
com.zj.proxy.Subject.operation1()

args: null

Realer do operation1

**** proxy: ****

class $Proxy0

method: public abstract void
com.zj.proxy.Subject.operation2(java.lang.String)

args:
[Ljava.lang.Object;@de6f34

ZJ

Realer do operation2 with ZJ

从结果可以发现,通过代理可以得到当前被调用的方法,及其参数。代理过程可以基于此进行逻辑处理,测试程序只是简单的打印这些相关信息。

本文出自 “子 孑
” 博客,请务必保留此出处/article/4381728.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: