Spring的AOP是基于动态代理机制实现的。关于AOP Spring官方网站有这样一段描述:
Spring AOP defaults to using standard JDK dynamic proxies for AOP proxies. This enables any interface (or set of interfaces) to be proxied.
Spring AOP can also use CGLIB proxies. This is necessary to proxy classes rather than interfaces. CGLIB is used by default if a business object does not implement an interface. As it is good practice to program to interfaces rather than classes; business classes normally will implement one or more business interfaces. It is possible to force the use of CGLIB, in those (hopefully rare) cases where you need to advise a method that is not declared on an interface, or where you need to pass a proxied object to a method as a concrete type.
大致意思是:Spring AOP机制默认基于JDK 动态代理来实现也可以设置基于CGLib动态代理来实现。
我们知道JDK动态代理类,通过继承和被代理类相同的Interface来实现对原有方法的调用和增强。而CGLib动态代理类,则通过继承被代理类的方式实现对原有方法的调用和增强。
Spring 注解类(包含Transactional)都是基于Spring AOP机制实现的。这里引出Transactional使用的禁忌(也是其它注解的使用禁忌):
1. 不建议将Transactional标注在Interface上
Transactional注解即可以注在在Interface的方法上。又可以写在具体的Class上。而如果标注在Interface上且配置Spring AOP使用CGLib动态代理。会导致Transactional失效。原因看上面分析。
2.不能将Transactional标注在private、protected方法上
Transactional 标签必须标注在public修饰的方法上,否则Transactional同样不生效。
3. 不能将Transactional标注在内部调用的方法上
Transactional必须标注在给外部调用的接口上。如:不带Transactional注解的方法a,调用带有Transactional注解的方法b,事务同样不生效。
public class Demo {
public void a(){
b();
}
@Transactional
public void b(){
}
以上几条禁忌同样适用于Spring的其它注解