动态代理与AOP----7
InvocationHandler使用的注意事项
Proxy类II
----------- android培训、java培训、java学习型技术博客、期待与您交流! ------------
动态代理和AOP的最后一节课介绍一下InvocationHandler的使用注意事项
1. InvocationHandler使用的注意事项
1). InvocationHandler抛出空指针异常
这部分考虑的出发点是:
由于InvocationHandler的invoke方法返回值是Object类型(所有类型的父类),$Proxy的各种方法有各种类型的返回值。所以JVM会在$Proxy的方法中自动将invoke方法返回的Object类型的值做强制类型转换,转换到需要的子类或者基本数据类型。
(1). 一个invoke方法返回值是null的InvocationHandler的实现类
[1]. 实现类代码:
class InvocationHandlerX implements InvocationHandler{
public Object invoke(Object proxy, Methodmethod, Object[] args)
throws Throwable {
System.out.print("调用的动态代理类的方法是:"+ method.getName()+"**");
return null;
}
}
[2]. 测试代码
ClassLoader loader =Collection.class.getClassLoader();
Class<?>[] interfaces=ArrayList.class.getInterfaces();
InvocationHandler h =new InvocationHandlerX();
Collection proxyInstance=(Collection)Proxy.newProxyInstance(loader, interfaces, h);
(2). 方法的返回值类型是引用类型---测试代理类的toString()方法
[1]. 添加的测试代码
System.out.println(proxyInstance);
[2]. 打印结果
[3]. 结果分析
给出的打印结果是调用的动态代理类的toString方法。所以,要在头脑中勾画出动态代理类$Proxy0的toString方法,如下:
{1}. $Proxy0的toString方法代码
public String toString() {
ObjectretVal ="";
try {
Methodmethod =this.getClass().getMethod("toString", null);
retVal=h.invoke(this, method, null);
}catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return (String) retVal;
}
【 注意】这里把 Object retVal =""; 而不是null的 原因就是invoke方法返回也是null,避免混淆,所以 初始化赋值成 ""。
{2}. 执行System.out.println(proxyInstance);涉及到的其他的方法的源码。便于理解先将这些方法的源码列出来:proxyInstance的类型是Collection类型,所以调用的是println重载方法:
{2}1. PrintStream类的println源码之一
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
这个println先调用String的静态方法把Object类型的数据转换成String类型的数据,源码如下:
{2}2. String类的