1、在Spring中的应用
Spring在将Advice织入目标对象的Joinpoint是在运行时动态进行的。它采用的方式可能有两种,即JDK动态代理与CGLIB代理。Spring会根据具体的情况在两者之间切换。
实际情况如下:
Ø 如果目标对象实现了接口,那么Spring默认会采用JDK的动态代理实现AOP
Ø 如果目标对象实现了接口,也可以强制使用CGLIB生成代理来 实现AOP
Ø 如果目标对象没有实现接口,那么必须使用CGLIB生成代理来实现AOP
实例1:
目标对象实现了接口:
package com.bjpowernode.spring;
public class UserManagerImpl // {
implements UserManager {
public void addUser(String username, String password) {
// checkSecurity();
System.out.println("---------UserManagerImpl.add()--------");
}
}
可以看到采用的是JDK动态代理:
实例2:
目标对象没有实现了接口:
package com.bjpowernode.spring;
public class UserManagerImpl {
// implements UserManager {
public void addUser(String username, String password) {
// checkSecurity();
System.out.println("---------UserManagerImpl.add()--------");
}
}
可以看到采用的是CGLIB代理:
2、JDK动态代理与CGLIB代理区别
*JDK动态代理对实现了接口的类进行代理
*CGLIB代理可以对普通类代理,主要对指定的类生成一个子类,因为是继承,所以我们的目标类最好不要使用Final声明 。提供代理类的功能是为了让以前的或第三方的没有实现接口的类也能够被通知,被标记为final的方法不能被通知。
3、如何强制使用CGLIB生成代理
*加入CGLIB库:Spring_HOME/lib/cglib/*.jar
*在Spring配置文件中加入如下配置,强制使用CGLIB代理
<aop:aspectj-autoproxyproxy-target-class="true"/>
4、总结
CGLib所创建的动态代理对象的性能比JDK所创建的代理对象性能高不少,但CGLib在创建代理对象时所花费的时间却比JDK动态代理多很多,所以对于singleton的代理对象或者具有实例池的代理,因为无需频繁的创建新的实例,所以比较适合CGLib动态代理技术,反之则适用于JDK动态代理技术。另外,由于CGLib采用动态创建子类的方式生成代理对象,所以不能对目标类中的final,private等方法进行处理。所以,大家需要根据实际的情况选择使用什么样的代理了。