由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的实例不是代理类,因此事务也就失效了!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。