您的位置:首页 > 其它

设计模式之动态代理

2010-08-16 20:32 316 查看
静态代理和动态代理同属于代理模式,作用是一样的,只是在实现起来是不同的,动态代理,也就是说代理是动态生成的。

package viekie.du.proxy;

public interface Moveable {

public void move();

}

Car这个类是需要被代理的对象

package viekie.du.proxy;

import java.util.Random;

public class Car implements Moveable {

@Override

public void move() {

System.out.println("car moving");

try {

Thread.sleep(new Random().nextInt(10000));

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

InvocationHandler 接口定义了一系列规则接口

package viekie.du.proxy;

import java.lang.reflect.Method;

public interface InvocationHandler {

public void invoke(Object o, Method m
);////Method参数很重要,用来以后通过反射机制动态的调用被代理的对象的m方法

}

TimeHandler 实现这个接口,在invoke方法中定义了规则

package viekie.du.proxy;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

public class TimeHandler implements InvocationHandler{

private Object target;
///////////在处理规则类中拥有一个被代理的对象,以便在invoke方法中利用发射调用m方法

public TimeHandler(Object target) {

this.target = target;

}

@Override

public void invoke(Object o, Method m) {

long start = System.currentTimeMillis();

System.out.println("start time : " + start);

try {

m.invoke(target);

} catch (Exception e) {

e.printStackTrace();

}

long end = System.currentTimeMillis();

System.out.println("total time = " + (end-start));

}

}

Proxy类利用反射机制负责动态的生成代理类,然后将该代理加载到内存。

package viekie.du.proxy;

import java.io.File;

import java.io.FileWriter;

import java.lang.reflect.Constructor;

import java.lang.reflect.Method;

import java.net.URL;

import java.net.URLClassLoader;

import java.util.Iterator;

import javax.tools.JavaCompiler;

import javax.tools.JavaCompiler.CompilationTask;

import javax.tools.StandardJavaFileManager;

import javax.tools.ToolProvider;

public class Proxy {

public static Object getNewProxyInstance(Class interfaces, InvocationHandler h) throws Exception{

String rt = "/r/n";

String methodString = "";

Method[] methods = interfaces.getMethods();

///查找所有的interface中的方法

for(Method m : methods){

methodString += "@Override" + rt +

"public void " + m.getName() + "() {" + rt +

" try {" + rt +

" Method md = " + interfaces.getName() + ".class.getMethod(/"" + m.getName() + "/");" + rt +

" h.invoke(this, md);" + rt +

" }catch(Exception e) {e.printStackTrace();}" + rt +

"}";

}

String src =

"package viekie.du.proxy;" + rt +

"import java.lang.reflect.Method;" + rt +

"public class $Proxy1 implements " + interfaces.getName() + "{" + rt +

" public $Proxy1(InvocationHandler h) {" + rt +

" this.h = h;" + rt +

" }" + rt +

" viekie.du.proxy.InvocationHandler h;" + rt +

methodString +

"}";

利用拼串的方式生成java文件

,并且写入到硬盘

String fileName = "d:/src/viekie/du/proxy/$Proxy1.java";

File file = new File(fileName);

FileWriter fWriter = new FileWriter(file);

fWriter.write(src);

fWriter.flush();

fWriter.close();

//加载该文件,并且编译

JavaCompiler javaComp = ToolProvider.getSystemJavaCompiler();

StandardJavaFileManager fileMgr = javaComp.getStandardFileManager(null, null, null);

Iterable iter = fileMgr.getJavaFileObjects(fileName);

CompilationTask t = javaComp.getTask(null, fileMgr, null, null, null, iter);

t.call();

fileMgr.close();

URL[] urls = new URL[]{new URL("file:/" + "d:/src/"
)};/////本地加载

URLClassLoader loader = new URLClassLoader(urls);

Class c = loader.loadClass("viekie.du.proxy.$Proxy1");

Constructor constr = c.getConstructor(InvocationHandler.class);
//利用字节码获取构造方法

return constr.newInstance(h); /// 返回构造对象

}

}

测试类

package viekie.du.proxy;

public class Main {

public static void main(String[] args) throws Exception {

Car t = new Car();

InvocationHandler h = new TimeHandler(t);

Moveable m = (Moveable)Proxy.getNewProxyInstance(Moveable.class, h);

m.move();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: