由Spring Boot 如果一个service @Transactional所在办法不是public会产生什么?咱们能够晓得,当一个servie 中被@Transactional润饰的办法全部都是no-public的时候,Spring不会创立代理类,也就是咱们的事务没有方法失效~。
那要是@Transactional润饰的办法有no-public,也有public的时候呢?这种状况下,spring 也是会创立代理类的。那么问题来了,如果这个public办法 调用了一个no-public 办法呢?有两种状况:
1. 这个no-public 办法上有一个帽子(@Transactional);2. 这个no-public 办法上没有帽子;
上面详细分析:
图1
final void testSaveAd() { try { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { var10000.intercept(this, CGLIB$testSaveAd$0$Method, CGLIB$emptyArgs, CGLIB$testSaveAd$0$Proxy); } else { super.testSaveAd(); } } catch (Error | RuntimeException var1) { throw var1; } catch (Throwable var2) { throw new UndeclaredThrowableException(var2); } }
public final void testSaveAd2() { try { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { var10000.intercept(this, CGLIB$testSaveAd2$1$Method, CGLIB$emptyArgs, CGLIB$testSaveAd2$1$Proxy); } else { super.testSaveAd2(); } } catch (Error | RuntimeException var1) { throw var1; } catch (Throwable var2) { throw new UndeclaredThrowableException(var2); } }
final void save() { try { MethodInterceptor var10000 = this.CGLIB$CALLBACK_0; if (var10000 == null) { CGLIB$BIND_CALLBACKS(this); var10000 = this.CGLIB$CALLBACK_0; } if (var10000 != null) { var10000.intercept(this, CGLIB$save$2$Method, CGLIB$emptyArgs, CGLIB$save$2$Proxy); } else { super.save(); } } catch (Error | RuntimeException var1) { throw var1; } catch (Throwable var2) { throw new UndeclaredThrowableException(var2); } }
下面三段code,别离是代理类对咱们定义的三个办法进行增强解决的状况;
@SpringBootTest@RunWith(SpringRunner.class)public class TransactionTest { @Autowired private TransactionServiceTest transactionServiceTest; @Test public void tansTest() { transactionServiceTest.testSaveAd2(); }}
运行下面的测试用例控制台没有输入 "commit" 的字眼
来,换一个测试姿态:
import java.lang.reflect.Method;@Slf4j@SpringBootTest@RunWith(SpringRunner.class)public class TransactionTest { @Autowired private TransactionServiceTest transactionServiceTest; @Transactional(rollbackFor = Exception.class) @Test public void tansTest2() throws Exception { invokeMethod(transactionServiceTest,"testSaveAd",null,null); } public static Object invokeMethod(Object owner,String methodName,Class[] argsClass,Object[] args) throws Exception{ Object objRtn = null; Class ownerClass = owner.getClass(); Method method = ownerClass.getDeclaredMethod(methodName, null); //Method method = ownerClass.getMethod(methodName, argsClass); method.setAccessible(true); method.invoke(owner, args); } }
上面是日志输入:
Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6904f5a0]
oh,no 呈现了扎眼了 "commit"。这是为什么呢?
图2
看到了吗,TransactionServiceTest的实例不是代理类,因而事务也就生效了!