动态代理角色:
一个真实角色:
一个抽象角色:真实角色实现的接口,代理角色也必须实现这个接口;
一个由Proxy类在运行时动态生成的代理角色$Proxy0;
一个实现InvocationHandler接口的类,可能看成是二级代理。
它们的关系及原理:
1. 首先由Proxy动态生成一个代理角色,这个代理角色会实现真实角色的接口,并关联到InvocationHandler的处理类handle;
2. 代理角色会重写接口中的方法,并在方法中调用handle的invoke方法,把proxy对象,Method对象,及方法的参数传给invoke;
3. 在handle的invoke方法,使用反射调用真实角色的方法。
一、抽象角色:Subject.java
package dynamicproxy;
public interface Subject
{
public void request();
}
二、真实角色:RealSubject.java
package dynamicproxy;
public class RealSubject implements Subject
{
public void request()
{
System.out.println("From real subject!");
}
}
三、实现InvocationHandler接口的处理类:DynamicSubject.java
package dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class DynamicSubject implements InvocationHandler
{
//被代理的对象
private Object sub;
public DynamicSubject(Object obj)
{
this.sub = obj;
}
//invoke中的参数由Proxy类生成的动态代理对象提供
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;
}
}
三、在客户端生成动态代理类:Client.java
package dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Client
{
public static void main(String[] args)
{
RealSubject realSubject = new RealSubject();
InvocationHandler handler = new DynamicSubject(realSubject);
Class<?> classType = handler.getClass();
Subject subject = (Subject) Proxy.newProxyInstance(classType
.getClassLoader(), realSubject.getClass().getInterfaces(),
handler);
/*
* 这个语句作了三件事情:
* 1.在运行时生成一个动态代理类$proxy0,这个类由加载classType对象的加载器加载
* 2.这个类实现了Subject接口;
* 3.这个类重写了request方法,在request方法中调用handler的invoker方法
*/
subject.request();
System.out.println(subject.getClass());
}
}
使用动态代理模式,被代理的对象(RealSubject类)可以在运行时动态改变;要控制的接口(Subject接口)也可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系。
动态代理的工厂方式见:
http://tiro-li.iteye.com/blog/1901661