您的位置:首页 > 其它

学习动态代理stepbystep(3)

2011-10-18 19:09 246 查看
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只是实现了时间代理,但我还想有日志代理,验证代理,……等等,那我该怎么办呢?且听下回分解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: