總結(jié)
- 只支持public方法
- 無法支持內(nèi)部調(diào)用
場景和原理分析
場景
- 只支持public方法
@Transactional
public List<Area> getAreaList(int pageNo, int pageSize) {
RowBounds rowBounds = new RowBounds(pageNo, pageSize);
return areaMapper.getAreaList(rowBounds);
}
- 無法支持內(nèi)部調(diào)用
@Override
public List<Area> getAreaList(int pageNo, int pageSize) {
RowBounds rowBounds = new RowBounds(pageNo, pageSize);
return areaMapper.getAreaList(rowBounds);
transactionTest();
}
@Transactional
public void transactionTest(){
//假裝有需要事務(wù)的操作
}
當(dāng)然,idea還是很智能的
原理分析
我們都知道,spring的注解功能基本上都是通過spring aop,注解加切面才能完美的實現(xiàn)各種功能。當(dāng)然褒翰,spring aop都是通過生成代理對象的方式實現(xiàn)的,也就是在代理對象中對你想要調(diào)用的方法進行了增強匀泊。
反之而言优训,你不使用代理對象,注解無效各聘。接下來看@Transactional的實現(xiàn)方式揣非。
在TransactionInterceptor中可以看到
@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
@Override
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
}
而invokeWithinTransaction方法是使用調(diào)用TransactionAspectSupport中的方法,下面貼關(guān)鍵代碼:
// Standard transaction demarcation with getTransaction and commit/rollback calls.
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
commitTransactionAfterReturning(txInfo);
return retVal;
明顯可以看到只是在方法前后進行了增強躲因,也就是說內(nèi)部調(diào)用方法未使用代理對象早敬,無法進行增強也就無法開啟事務(wù)忌傻。
@Transactional 只能應(yīng)用到 public 方法才有效
只有@Transactional 注解應(yīng)用到 public 方法,才能進行事務(wù)管理搞监。這是因為在使用 Spring AOP 代理時水孩,Spring 在調(diào)用在圖 1 中的 TransactionInterceptor 在目標(biāo)方法執(zhí)行前后進行攔截之前,DynamicAdvisedInterceptor(CglibAopProxy 的內(nèi)部類)的的 intercept 方法或 JdkDynamicAopProxy 的 invoke 方法會間接調(diào)用 AbstractFallbackTransactionAttributeSource(Spring 通過這個類獲取表 1. @Transactional 注解的事務(wù)屬性配置屬性信息)的 computeTransactionAttribute 方法琐驴。如圖:
protected TransactionAttribute computeTransactionAttribute(Method method,
Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;}
引用:https://www.ibm.com/developerworks/cn/java/j-master-spring-transactional-use/index.html