代码演示
// 拦截器
public interface DemoInterceptor extends MethodInterceptor {
}
// 被代理的接口
public interface DemoProxyI {
}
// 被代理的类
public class DemoProxy implements DemoProxyI{
}
public class Main {
public static void main(String[] args) {
DemoProxy demoProxy = new DemoProxy();
ProxyFactory proxyFactory = new ProxyFactory(demoProxy);
proxyFactory.addAdvice(new DemoInterceptor() {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("echo be intercepted!!!");
return "proxy";
}
});
demoProxy = (DemoProxy) proxyFactory.getProxy();
}
}
当我们执行main函数的时候,会出现异常。
原因解析
为什么呢?让我们来看一下源码,当我们的类继续了接口会默认使用JDK动态代理,这个时候我们用子类类接收对象就会产生这个强转错误。如果我们写成如下形式,使用接口去接收这个对象则不会有这个错误:
DemoProxyI demoProxyI = (DemoProxyI) proxyFactory.getProxy();
这里就涉及到父类与子类的转换问题了:
- 父类接口不能直接转换为子类对象,除非实际对象本身就是子类的实例。
- 向下转型需要使用
instanceof
检查类型,以确保安全。 - 如果实际对象不是目标子类的实例,强制转换会抛出
ClassCastException
。
那如果我就想用上面的写法怎么办呢?其实也是有办法的我们使用CGLIB的代理就好了,因为CGLIB的代理是基于类继承的,所以不会有上面的问题。
// 通过类继承的方式来实现动态代理
proxyFactory.setProxyTargetClass(true);
// 或者可设置
proxyFactory.setOptimize(true);