Spring的AOP的限制:
aop无法拦截方法内部的调用,假如有方法
public class AccountServiceImpl implements AccoutService{
@Transactional
public void increment(Account account, int amount){
doXXX();
}
@Transactional
public void decrement(Account account, int amount) {
doXXX();
}
public void transform(Account from,Account to,int amout){
decrement(from,amount);
increment(to,amount);
}
}
transform方法内部的decrement();increment()虽然有Transactional,但是事物拦截器不会拦截到这两个方法调用
cglib则可以解决此类问题,cglib的代理可以通过字节码增强,生成代理类型的子类型,并创建对象。
但,在spring中不论你用cglib,还是jdk动态代理都会存在上述问题。
根本原因是spring的代理是基于目标对象的代理而不是像cglib一样直接生成目标类型的子类型,像静态代理一样对目标对象的方法调用做一层包裹,并不管目标对象方法的内部调用。
看看Spring的
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
private final MethodProxy methodProxy;
private boolean protectedMethod;
public CglibMethodInvocation(Object proxy, Object target, Method method, Object[] arguments,
Class targetClass, List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
this.methodProxy = methodProxy;
this.protectedMethod = Modifier.isProtected(method.getModifiers());
}
/**
* Gives a marginal performance improvement versus using reflection to
* invoke the target when invoking public methods.
*/
@Override
protected Object invokeJoinpoint() throws Throwable {
if (this.protectedMethod) {
return super.invokeJoinpoint();
}
else {
return this.methodProxy.invoke(this.target, this.arguments);
}
}
}
看到其中的return this.methodProxy.invoke(this.target, this.arguments); 在target目标上直接做invoke,所以不论methodProxy内部有什么方法调用
spring都是无法感知的