学习动态代理stepbystep(3)

1.
以上,完成了动态代理的生成。
但它是实现了Moveable接口的动态代理,
而我们想要的是实现任意接口的代理。


2.
因此,我们要修改的是,拼接sql语句的字符串:
建立Proxy.java
public static Object newProxyInstance throws Exception{
}


将刚才所写的测试方法全部拷贝至此方法当中,既然要实现多种接口的代理,那么参数中有必要写个接口的:
故改写为:
public static Object newProxyInstance(class infce) throws Exception{

}
动态拼接要代理的类:


将原来的语句("public class TankTimeProxy implements Moveable {" + rt + )修改为
//此处用infce.getName()来拿到要被代理的类的接口的名字
//注意:此处要用infce.getName(),因为如果只是用infce,则会调用它的toString方法,会在类前面自动加上interface
"public class TankTimeProxy2 implements " +infce.getName() + "{" + rt +
运行,也许会出会错误,但是不要紧,我们这一步只是想完成代理对象的变化,只需关心它生成的java文件是否符合我们的希望就可以了。
看到生成的类是:public class TankTimeProxy implements com.compiler.test.Moveable
OK,成功。


这样呢,我们就完成了对于任意类的代理。


但是,我们将代理的方法move(),写死了。这是我们所不希望的,我们希望可以自动找到接口中的方法。


3.
先建立一个小测试文件好了:Test.java
public class Test2 {
///用反射,来知道 一个接口中有多少个方法
///站在classloader的角度,对象 中的方法也是对象
public static void main(String[] args) {
//import java.lang.reflect.Method;
Method[] methods = com.compiler.test.Moveable.class.getMethods();
for(Method m:methods){
System.out.println(m); //打印结果:public abstract void com.compiler.test.Moveable.move()
System.out.println(m.getName()); //打印结果:move
}
}
}


也就是说,我们可以用上面的方式来获得接口中的方法。测试成功后,我们把它引入到我们的Proxy.java中:
//但要注意,不能再用 com.compiler.test.Moveable.class.getMethods(),因为我们要用任意的类,所以应改为infce.getMethods();
代码如下:


String rt = "\r\n";
///用于method的字符串
String methodStr = "";
Method[] methods = infce.getMethods();
for(Method m:methods){
methodStr = methodStr + "@Override" + rt +
"public void " + m.getName() + "(){" + rt +
"\t\tlong start = System.currentTimeMillis();" + rt +
"\t\tt." + m.getName()+ "();" + rt +
"\t\tlong end = System.currentTimeMillis();" + rt +
"\t\tSystem.out.println(\"time: \" + (end - start));" + rt +
"\t}";
}
System.out.println(infce);
String str =
"package com.compiler.test;" + rt +
"public class TankTimeProxy2 implements " +infce.getName() + "{" + rt +
"\tpublic TankTimeProxy2(Moveable t){" + rt +
"\tsuper();" + rt +
"\tthis.t = t;" + rt +
"\t}" + rt +
"\tMoveable t;" + rt +
//将这里替换
methodStr +
"}";


这样呢,我们就完成了为每一个方法加上了一个时间代理。(注意,其中函数的返回值可以通过反映拿到。这里简写为都是void类型的)


另外,既然是实现了任意接口的代理,代码的结尾处:
Moveable m = (Moveable)ctr.newInstance(new Tank());
m.move();
也要改为:
//用到了反射
生成一个类的对象,现在需要把它返回去。由于不知道是什么接口,所以用Object
Object o = (Object)ctr.newInstance(new Tank()); //传入参数,正式生成对象
return o;




测试:Client.java中:


public static void main(String[] args) throws Exception {
// Moveable m =(Moveable) Proxy.newProxyInstance(Moveable.class);
Moveable m =(Moveable) Proxy.newProxyInstance(Comparable.class); //生成的文件会有编译错误,不过不要紧,我们只是看到生成的文件中,被代理的类和被重写的方法已经达到要求就可以了。
m.move();
}


好了,到目前为止,我们已经做到了:我们可以不同的类,并重写各种类中的方法了。
我们现在也可以做个小小的屏蔽:指定在其他地方生成.java文件和class文件,这样,在项目中就真正看到代理了文件了。
由于用途不大,我就没做这个的试验。


ok,又到了提出问题的时候了。现在的问题是:
这个newProxyInstance只是实现了时间代理,但我还想有日志代理,验证代理,……等等,那我该怎么办呢?且听下回分解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值