所谓动态代理就是代理类在程序运行期间运用反射机制动态创建而成。是根据代理的创建时期相对于静态代理的另一种代理设计模式。静态代理的,clas文件在程序运行前就已经存在。例外要说明的是代理模式实际上是对象的适配器模式的扩展,他的目的是扩展类中方法的功能。
先来看看静态代理的例子:
//需要共同实现的接口
public interface Sourceable
{
public void method();
}
//一个实现了公共接口的类
public class Source implements Sourceable
{
public void method()
{
System.out.println("the original method");
}
}
//实现了同一接口的代理类
public class Proxy implements Sourceable
{
private Source source;
public Proxy()
{
super();
this.source = new source();
}
public void method()
{
before();
source.method();
after();
}
public void before()
{
System.out.println("before.....do something");
source.method();
System.out.println("after......do something")
}
}
从中可以看出静态代理模式的每个代理类只能为一个接口服务,而且每个代理类除了接口不同以外其他的代码实现基本上没有太大的变动,这样就会造成严重的代码重复。解决这个问题的方法是用动态代理模式,通过一个代理来完成全部代理的功能。动态代理类要实现InvocationHandler接口,此接口中有一个方法:
invke(Object proxy,Method method,Objdect[] args);
proxy: 被代理的对象
method: 被代理类中的方法
args: 方法的参数
Proxy类是一个专门完成代理的操作类。其中有一个静态方法newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) ; 该函数返回
loader: 被代理 对象的类加载器,集对象.getClass().getClassLoader();
interfaces: 得到全部的接口
InvocationHanlder h: 实现了InvocationHanlder 接口的类实例;
一个简答的例子的实现(该例子得到一个对象中所有方法的运行时间,用动态代理实现):
public proxyTest
{
public static void main(String[] args)
{
ArrayList<String> list = new ArrayList<String>();
Collection<String> proxy = getProxy(list);
proxy.add("a");
proxy.add("b");
}
public static Object getProxy(final Object target)
{
Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable{
long startTime = System.currentTimeMillis();
Object revVal = method.invoke(target, args);
try
{
Thread.sleep((long)(Math.random()*1000));
} catch (Exception e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println(method.getName()+" running time is : "+(endTime - startTime));
return revVal;
}
});
return proxy;
}
}
invoke函数中因为方法执行的时间太短,几乎为零,为了看得更清楚,因此加了线程睡眠,就当是被代理对象方法中执行了此语句。
很显然此种代理模式只能代理有实现了接口的类。
|