代理模式(Proxy)-利用反射机制实现的动态代理
Java深入到一定程度,就不可避免的碰到设计模式这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的 中型系统中应用广泛,遵循一定的编程模式,才能使自己的代码便于理解,易于交流,Proxy(代理)模式是比较常用的一个模式.
在应用中,有些对象有时候由于跨越网络或者其他的障碍,而不能够或者不想直接访问另一个对象,如果直接访问会给系统带来不必要的复杂性,这时候可以在客户 程序和目标对象之间增加一层中间层,让代理对象来代替目标对象打点一切。
Proxy 的使用场景:
1.远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象。这个不同的地址空间可以是在本机器中,也可是在另一台机器中。远程 代理又叫做大使(Ambassador)。好处是系统可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。客户完全可以认为被代理的对象是局域的而 不是远程的,而代理对象承担了大部份的网络通讯工作。由于客户可能没有意识到会启动一个耗费时间的远程调用,因此客户没有必要的思想准备。
2.虚拟(Virtual)代理:根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建。使用虚拟代理模式的好处就是代理对象可以在 必要的时候才将被代理的对象加载;代理可以对加载的过程加以必要的优化。当一个模块的加载十分耗费资源的情况下,虚拟代理的好处就非常明显。
3.Copy-on-Write代理:虚拟代理的一种。把复制(克隆)拖延到只有在客户端需要时,才真正采取行动。
4.保护(Protect or Access)代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。保护代理的好处是它可以在运行时间对用户的有关权限进行 检查,然后在核实后决定将调用传递给被代理的对象。
5.Cache代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
6.防火墙(Firewall)代理:保护目标,不让恶意用户接近。
7.同步化(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突。
8.智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。
这里介绍的是如何利用反射机制实现动态代理:
最常见的情况是:但一个应用已经开发结束后,我们需要对针对一些对象的操作记录日志 或者做一些额外的工作;在这种情况下我们如果为每一个对象设计一个代理类的话显然会增加很多工作量,如果采用反射机制的话就可以轻松的解决这个问题。
在此写了4个java类来描述说明Proxy设计模式的动态代理实现方式;
1、 ReflectProxy.java 动态代理类
2、 IHelloWorld.java HelloWorld接口
3、 HelloWorld.java HelloWorld实现类
4、 ReflectProxyText.java 带有main方法的测试类
=============== 1、 ReflectProxy.java
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//通过实现InvocationHandler接口的invoke方法 促使 被代理对象的方法别调用时都会出发invoke方法
public class ReflectProxy implements InvocationHandler {
// 被代理的对象
private Object proxyObject;
public ReflectProxy(Object proxyObject) {
this.proxyObject = proxyObject;
}
// 通过工厂模式生成一个代理对象
public static Object factory(Object proxyObject) {
Class cls = proxyObject.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(),
cls.getInterfaces(), new ReflectProxy(proxyObject));
}
//InvocationHandler 接口中的方法
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//在调用被代理类的实际方法前的操作
doBeforeCalling(method);
//输出被代理类的实际方法中的参数
if (args != null) {
for (int i = 0; i < args.length; i++) {
System.out.println("args[" + i + "]=" + args[i] + "");
}
}
//调用被代理类的实际方法
Object o = method.invoke(proxyObject, args);
//在调用被代理类的实际方法后的操作
doAfterCalling(method);
return o;
}
//在调用被代理类的实际方法前的操作
private void doBeforeCalling(Method method){
System.out.println("before calling [" + method + "]");
}
//在调用被代理类的实际方法后的操作
private void doAfterCalling(Method method){
System.out.println("after calling [" + method + "]");
}
}
=============== 1 end
=============== 2、 IHelloWorld.java
package proxy;
public interface IHelloWorld {
public void sayHello();
public void sayBye();
public void saySomething(String msg);
}
=============== 2 end
=============== 3、 HelloWorld.java
package proxy;
public class HelloWorld implements IHelloWorld {
public void sayBye() {
System.out.println("Hello World!");
}
public void sayHello() {
System.out.println("Bye!");
}
public void saySomething(String msg) {
System.out.println(msg);
}
}
=============== 3 end
=============== 4、 ReflectProxyText.java
package proxy;
import java.util.ArrayList;
import java.util.List;
public class ReflectProxyText {
public static void main(String[] args) {
try {
//代理List接口对象
Object obj = ReflectProxy.factory(new ArrayList<Object>(0));
List list = (List)obj;
list.add("A");
list.add("B");
//代理IHelloWorld接口对象
obj = ReflectProxy.factory(new HelloWorld());
IHelloWorld helloWorld = (IHelloWorld)obj;
helloWorld.sayHello();
helloWorld.saySomething("How is everything!");
helloWorld.sayBye();
} catch (Exception e) {
e.printStackTrace();
}
}
}
=============== 4 end
这里介绍的是常见的代理实现;
在此写了4个java类来描述说明Proxy设计模式实现方式;
1、 ProxySubject.java 代理类
2、 ISubject.java RealSubject接口
3、 RealSubject.java RealSubject
4、 ProxyTest.java 带有main方法的测试类
=============== 1、 ProxySubject.java
package proxy;
public class ProxySubject implements ISubject {
private ISubject subject;
private ProxySubject() {
}
public ProxySubject(ISubject subject) {
if (subject == null)
subject = new RealSubject();
this.subject = subject;
}
public void request() {
preRequest();
this.subject.request();
postRequest();
}
private void preRequest() {
System.out.println("pre request.");
}
private void postRequest() {
System.out.println("post request.");
}
}
=============== 1 end
=============== 2、 ISubject.java
package proxy;
public interface ISubject {
public void request();
}
=============== 2 end
=============== 3、 RealSubject.java
package proxy;
public class RealSubject implements ISubject {
public void request() {
System.out.println("This is realSubject request!");
}
}
=============== 3 end
=============== 4、 ProxyTest.java
package proxy;
public class ProxyTest {
public static void main(String[] args) {
ISubject subject = new ProxySubject(new RealSubject());
subject.request();
}
}
=============== 4 end