首先在Spring开发参考手册中描述是这样子的,Spring AOP部分使用JDK动态代理或者CGLIB来为目标对象创建代理。(建议优先使用JDK的动态代理)。如果被代理的目标对象实现了至少一个接口,则会使用JDK动态代理。所有该目标类型实现的接口都将被代理。 若该目标对象没有实现任何接口,则创建一个CGLIB代理。
当使用CGLIB时,需要引入相应的jar包。
那为什么Spring中优先建议使用JDK的动态代理呢?为什么要使用接口呢?第一个问题,
不知道为什么,我唯一能解释的是,如果面向接口编程更符合编程规范,多整体的扩展性也更好。这里贴下JDK和CGLIB的简单区别:
* JDK动态代理只能对实现了接口的类生成代理,而不能针对类。
* CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法。
因为是继承,所以该类或方法最好不要声明成final。
第二个问题,困扰了我一短时间,查阅了一些文章以后,总结如下:首先关于动态代理,
public static Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h) throws IllegalArgumentException
接受的第二个参数是一组接口的列表,代理实例根据这个接口来创建代理对象,从而实现代理。 JDK动态代理的原理是根据定义好的规则,用传入的接口创建一个新类,这就是为什么采用动态代理时为什么只能用接口引用指向代理,而不能用传入的类引用执行动态类。
在使用Spring中,如果将代理对象转换成一个借口的实现类,就会抛出异常
java.lang.ClassCastException: $Proxy0 cannot be cast to...
另外使用接口的设计,是面向接口编程的一种编程规范,有利于以后不同业务逻辑的扩展,使得开发更加有伸缩性。