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

<<interface>>Subject.java
package com.zj.proxy;
public interface
Subject {
void
operation1();
void
operation2(String arg);
}
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 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);
}
}
|
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
从结果可以发现,通过代理可以得到当前被调用的方法,及其参数。代理过程可以基于此进行逻辑处理,测试程序只是简单的打印这些相关信息。