1.问题描述:
出现异常:
Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to com.spring.proxy.serviceImpl
由异常追溯动态代理的源头
2.过程
2.1:我们java创建动态代理的简单实现:代码如下:
service实现的代码:
public class CalculatorImpl implements Calculator {
@Override
public int add(int i, int j) {
System.out.println("add");
return i+j;
}
}
动态代理的代码:
public class CalculatorProxy {
public Calculator getCalculatorProxy(final Calculator calculator) throws InstantiationException, IllegalAccessException{
ClassLoader loader = calculator.getClass().getClassLoader();
Class<?>[] interfaces = calculator.getClass().getInterfaces();
InvocationHandler handler = new InvocationHandler() {
/**
* Object:这是代理的对象 ,一般不会使用它,有可能会造成内存溢出的现象
*
* Method:正在被调用的方法
*
* Object[]:方法的参数
*/
@Override
public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
// //调用方法前
System.out.println("this is "+arg1.getName()+"doing Start..");
Object o = arg1.invoke(calculator, arg2);
// //调用结束
System.out.println("this is "+arg1.getName()+"result ending..");
return o;
}
};
Calculator proxy = (Calculator) Proxy.newProxyInstance(loader ,
interfaces , handler);
return proxy;
}
}
测试代码:
public class CalculatorMain {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
CalculatorImpl impl = new CalculatorImpl();
Calculator calculator2 = new CalculatorProxy().getCalculatorProxy(impl);
calculator2.add(1, 2);
System.out.println(calculator2);
}
}
2
.2:我们从代码上面知道:
第一步:调用:Proxy.newProxyInstance(loader ,interfaces , handler);,所以打开源码:
第二步:因为时间关系就不给源码了:大致如下:
由newProxyInstance中的getProxyClass会生成一个com.sun.proxy.Proxy$0的类,这个类继承了Proxy实现了service接口; 所以上面的异常就可以解释了:因为serviceImpl也是实现的service接口,所以当你使用实现类做为代理的对象就会出现:
Exception in thread "main" java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to com.spring.proxy.xxx
第三步:题外补充:
在proxy$0这个类中有一个静态代码块:这个代码块里面加载了class.forname(sevice)的;
在proxy$0这个类还有一个实现了service的方法:在这个方法里面调用了handler的invoke方法;所以就间接地调用了其他实现类的实现的方法;
好问题大概就是这样了!!!