# 有关事务失效的问题

JAVA 事务 2019-03-08

# 为什么@Transactional只能应用到public方法才有效

public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {
 	 protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
        //检查目标方法的修饰符是不是 public,若不是 public,就不会获取@Transactional 的属性配置信息,最终会造成不会用 TransactionInterceptor 来拦截该目标方法进行事务管理
        if (this.allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
            return null;
        } else {    
        //AopUtils.getMostSpecificMethod实际调用的是 ClassUtils.getMostSpecificMethod
            Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
            TransactionAttribute txAttr = this.findTransactionAttribute(specificMethod);
            if (txAttr != null) {
                return txAttr;
            } else {
            //获取事务属性信息
                txAttr = this.findTransactionAttribute(specificMethod.getDeclaringClass());
                if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
                    return txAttr;
                } else {
                    if (specificMethod != method) {
                        txAttr = this.findTransactionAttribute(method);
                        if (txAttr != null) {
                            return txAttr;
                        }

                        txAttr = this.findTransactionAttribute(method.getDeclaringClass());
                        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
                            return txAttr;
                        }
                    }

                    return null;
                }
            }
        }
    }
 }

说明

只有@Transactional 注解应用到 public 方法,才能进行事务管理。这是因为在使用 Spring AOP 代理时,Spring 在调用TransactionInterceptor在目标方法执行前后进行拦截之前,DynamicAdvisedInterceptor(CglibAopProxy 的内部类)的的 intercept 方法或 JdkDynamicAopProxy 的 invoke 方法会间接调用 AbstractFallbackTransactionAttributeSource(Spring 通过这个类获取 @Transactional 注解的事务属性配置属性信息)的 computeTransactionAttribute 方法。