由微见著,模拟JDK动态代理的实现1

话说代理说白了就是方法的再封装,实现代理是由继承和聚合两种方式实现的。动态代理就是使用代理类在运行时根据传入的接口类型的对象,生成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));
}




}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值