Spring AOP的两种代理方式

时间:2021-07-28 13:25:54

Spring AOP是通过为目标对象创建代理来实现的。其使用的代理方式有两种:

  • JDK 动态代理 (目标对象实现了接口时使用,只会代理目标接口方法)
  • CGLIB (当目标对象没有实现接口时只能使用CGLIB ,当然可以通过配置强制有接口的对象也使用CGLIB)

CGLIB是通过为目标对象生成的子类来实现代理,因此对于final修饰的方法没有作用。另外目标对象的构造方法将被调用两次。

CGLIB和JDK动态代理的优缺点:
- CGLIB执行代理的性能高,但是创建时耗费的时间长(通过操作目标对象的字节码创建);

配置proxy-target-class
通过配置可以强制Spring AOP只使用CGLIB :设置proxy-target-class=true;

<aop:config proxy-target-class="true">
    <!-- other beans defined here... -->
</aop:config>

<!--该参数也可在下面标签上使用 -->
<tx:annotation-driven/>
<aop:aspectj-autoproxy/>

注意
当一个bean定义为pointcut后, 若该bean使用了JDK动态代理,则getBean时必须使用其接口形式,且接口不能强转为其实现类,否则为报错。
代码如下:

// IPerson为接口, PersonService是其实现类 ,PersonService配置为pointcut
// getBean强转为实现类时运行报错 $Prox4 cannot be cast to PersonService
//IPerson person = (PersonService) context.getBean("person");

IPerson person = (IPerson) context.getBean("person");

// 当对person执行强转时同样报错 
PersonService service = (PersonService) person;

当使用CGLIB代理方式时不会有上述错误。