话说代理说白了就是方法的再封装,实现代理是由继承和聚合两种方式实现的。动态代理就是使用代理类在运行时根据传入的接口类型的对象,生成class文件,实例化,并调用里面的代理方法。
以下是例子(code):
/**
* 使用聚合来实现代理-代理和被代理也是实现Moveable(自定义Interface)
* 本类是模拟代理的测试端
* @author Rick
*
*/
public class Client {
public static void main(String[] args) throws Exception {
// Tank t = new Tank();
/*TankTimeProxy ttp = new TankTimeProxy(t);
TankLogProxy tlp = new TankLogProxy(ttp);*/
/**
* 替换代理顺序
*/
/*TankLogProxy tlp = new TankLogProxy(t);
TankTimeProxy ttp = new TankTimeProxy(tlp);
Moveable m = ttp;
m.move();
*/
/**
* 以上是静态代理,以下是动态代理,动态代理是不需要知道TankTimeProxy类的名字
*/
/**
* 能作为各种类对象的代理
*/
Moveable m = (Moveable) Proxy.newProxyInstance(Moveable.class);//所有代理由此方法产生
m.move();
}
}
---------------------------------------------------------------------------------------------------------------------------------------------
public interface Moveable {
void move();
}
---------------------------------------------------------------------------------------------------------------------------------------------
/**
* 实现任意接口的类的代理-使用聚合代理
* 代理模式有聚合代理和实现继承的代理
* 继承的方式的缺点就是:n级代理就需要n级继承关系
* @author Rick
*
*/
public class Proxy {
public static Object newProxyInstance(Class infce) throws Exception {//实现动态编译 --JDK Complier
String methodString = "";
String rt = "\r\n";
Method[] methods = infce.getMethods();
for(Method m : methods) {
methodString += "@Override" + rt +
"public void " + m.getName() + "() {" + rt +
" long start = System.currentTimeMillis();" + rt +
" System.out.println(\"start time : \" + start);" + rt +
" t."+ m.getName() + "();" + rt +
" long end = System.currentTimeMillis();" + rt +
" System.out.println(\"时间代理类运行时间: \" + (end - start));" + rt +
"}";
}
String src =
"package com.tamao.dynamicAgent;" + rt +
"public class TankTimeProxy implements "+ infce.getName() +" {" + rt +
" Moveable t;" + rt +
" public TankTimeProxy(Moveable t) {" + rt +
" super();" + rt +
" this.t = t;" + rt +
" }" + rt +
methodString +
"}";
String fileName = System.getProperty("user.dir")
+ "/src/com/tamao/dynamicAgent/TankTimeProxy.java";
File f = new File(fileName);;
FileWriter fw = new FileWriter(f);
fw.write(src);
fw.flush();
fw.close();
/**
* JDK6.0才有编译器
*/
//编译以上代码
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
Iterable units = fileMgr.getJavaFileObjects(fileName);
CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
t.call();
fileMgr.close();
//加载到内存并生成一个实例--同样适用于网络load来的类
URL[] urls = new URL[] {new URL("file://" + System.getProperty("user.dir") + "/src")};
URLClassLoader ul = new URLClassLoader(urls);
Class c = ul.loadClass("com.tamao.dynamicAgent.TankTimeProxy");
System.out.println(c);
/**
* 站在JVM的角度,拿到类的构造方法的对象(PS:找到方法是根据参数来决定的)
*/
//找到参数类型是Moveable的参数类型的构造方法
Constructor ctr = c.getConstructor(Moveable.class);
Object m = ctr.newInstance(new Tank());
return m;
}
}
---------------------------------------------------------------------------------------------------------------------------------------------
public class Tank implements Moveable {
@Override
public void move() {
long start = System.currentTimeMillis();
System.out.println("moving...");
try {
Thread.sleep(new Random().nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("Tank运行时间: " + (end - start));
}
}