须知
@Transactional 底层使用TransactionInterceptor类在方法执行前后开启事务和关闭事务
spring的动态代理,分为两种:jdk自身代理和cglib代理方式
参考:https://blog.csdn.net/a837199685/article/details/68930987
objenesis参考:http://objenesis.org/index.html 主要用于不用构造方法初始化实例
场景
case1
接口和实现类,test1中不加@Transactional,test2加@Transactional,外部调用test1()方法
结果:test2方法失败时,事务并不会回滚
//接口
public interface CeshiService {
void test1();
}
//test1方法上没有Transactional注解,test2方法上有Transactional注解
@Service
public class CeshiServiceImpl implements CeshiService{
public void test1(){
test2();
}
@Transactional(rollbackFor = Exception.class)
public void test2() {
Db.update("INSERT INTO \"public\".\"ceshi\"(\"id\", \"name\") VALUES (2, '2');");
throw new Exception("异常");
}
}
分析:
debug发下,CeshiServiceImpl中的this指向的是CeshiServiceImpl@11343 实例,并不是$.Proxy代理对象,那么当也就决定了内部调用test2时,不会走动态代理的链路,那么事务也就不会生效
case2
普通类,test1中不加@Transactional,test2加@Transactional,外部调用test1()方法
结果:test2方法失败时,事务并不会回滚
//test1方法上没有Transactional注解,test2方法上有Transactional注解
@Service
public class CeshiService{
public void test1(){
test2();
}
@Transactional(rollbackFor = Exception.class)
public void test2() {
Db.update("INSERT INTO \"public\".\"ceshi\"(\"id\", \"name\") VALUES (2, '2');");
throw new Exception("异常");
}
}
分析:
debug发下,CeshiServiceImpl中的this指向的是CeshiServiceImpl@11342 实例,并不是Enhanced代理对象,那么当也就决定了内部调用test2时,不会走动态代理的链路,那么事务也就不会生效
如何生效
-
首先开启exposeProxy,然后((CeshiService) AopContext.currentProxy()).test2();去调用test2内部方法
@Transactional 代码分析
TransactionInterceptor类
public Object invoke(final MethodInvocation invocation) throws Throwable {
Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
//主要来此处的invokeWithinTransaction方法,把真正的方法包围了
return this.invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
}
TransactionAspectSupport中的invokeWithinTransaction方法
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
//获取注解属性
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// 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;
}
else {
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus status) {
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
return invocation.proceedWithInvocation();
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
return new ThrowableHolder(ex);
}
}
finally {
cleanupTransactionInfo(txInfo);
}
}
});
// Check result: It might indicate a Throwable to rethrow.
if (result instanceof ThrowableHolder) {
throw ((ThrowableHolder) result).getThrowable();
}
else {
return result;
}
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
}
}
protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.hasTransaction()) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
"] after exception: " + ex);
}
// 注解上指定的回滚异常类型是否匹配
if (txInfo.transactionAttribute.rollbackOn(ex)) {
try {
//回滚 txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);
throw ex2;
}
catch (RuntimeException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
throw ex2;
}
catch (Error err) {
logger.error("Application exception overridden by rollback error", ex);
throw err;
}
}
else {
// We don't roll back on this exception.
// Will still roll back if TransactionStatus.isRollbackOnly() is true.
try {
//提交事务 txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by commit exception", ex);
ex2.initApplicationException(ex);
throw ex2;
}
catch (RuntimeException ex2) {
logger.error("Application exception overridden by commit exception", ex);
throw ex2;
}
catch (Error err) {
logger.error("Application exception overridden by commit error", ex);
throw err;
}
}
}
}
rollbackOn方法,从此可以看到,默认只要当是RuntimeException或Error异常时才会回滚,非RuntimeException的Exception默认不会回滚
@Override
public boolean rollbackOn(Throwable ex) {
return (ex instanceof RuntimeException || ex instanceof Error);
}
总结
我们发现不论是jdk动态代理还是cglib动态代理,执行类方法时,this对象始终是原始实例,也就决定了,内部调用时,不会触发动态代理里面的方法。