问题
一般来说,springboot实现事务只需要 在public方法头上加上@Transactional注解即可,@Transactional 默认只捕获RuntimeException.class,对Exception异常得需要 @Transactional(rollbackFor = {Exception.class}) 捕获回滚。这个有个问题就是:当项目特别大的时候,对所有的service 都去加上事务 ,显得非常麻烦。
方案
可以通过spring AOP 方式实现配置全局的transaction事务。JAVA代码例子如下:
package com.demo.app.datasource;
import com.demo.framelib.datasource.MultipleDataSource;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* Description:事务操作类.
事务管理配置,拦截指定包下所有方法
*/
@Aspect
@Component
@AutoConfigureAfter(MultipleDataSourceConfiguration.class)
public class TxAdviceInterceptor {
/**
* basicDataSource.
*/
@Value("${tx_method_timeout}")
private int txMethodTimeout;
/**
* basicDataSource.
*/
@Value("${aop_pointcut_expression}")
private String aopPointcutExpression;
/**
* DataSourceTransactionManager.
* @param multipleDataSource multipleDataSource
* @return dataSourceTransactionManager.
*/
@Bean(name = "dataSourceTransactionManager")
public DataSourceTransactionManager dataSourceTransactionManager(
@Qualifier("multipleDataSource") MultipleDataSource multipleDataSource) {
DataSourceTransactionManager dataSourceTransactionManager =
new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(multipleDataSource);
return dataSourceTransactionManager;
}
/**
* 事务配置
*/
@Bean(name = "txAdvice")
public TransactionInterceptor txAdvice(
@Qualifier("dataSourceTransactionManager") DataSourceTransactionManager dataSourceTransactionManager) {
/* 只读事务,不做更新操作 */
RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
readOnlyTx.setReadOnly(true);
readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
/* 当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务 */
RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
/*requiredTx.setTimeout(txMethodTimeout);*/
Map<String, TransactionAttribute> txMap = new HashMap<>();
txMap.put("add*", requiredTx);
txMap.put("create*", requiredTx);
txMap.put("modify*", requiredTx);
txMap.put("save*", requiredTx);
txMap.put("insert*", requiredTx);
txMap.put("update*", requiredTx);
txMap.put("delete*", requiredTx);
txMap.put("remove*", requiredTx);
txMap.put("get*", readOnlyTx);
txMap.put("query*", readOnlyTx);
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
source.setNameMap(txMap);
TransactionInterceptor txAdvice =
new TransactionInterceptor(dataSourceTransactionManager, source);
return txAdvice;
}
/**
* 利用AspectJExpressionPointcut设置切点
*/
@Bean(name = "txPointcut")
public AspectJExpressionPointcut txPointcut() {
AspectJExpressionPointcut txPointcut = new AspectJExpressionPointcut();
txPointcut.setExpression(aopPointcutExpression);
return txPointcut;
}
/**
* 声明切面(Aspect):切面就是通知和切入点的结合。
* 通知和切入点共同定义了关于切面的全部内容——它的功能、在何时和何地完成其功能
*/
@Bean
public Advisor txAdviceAdvisor(
@Qualifier("txAdvice") TransactionInterceptor txAdvice,
@Qualifier("txPointcut") AspectJExpressionPointcut txPointcut) {
DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor(txPointcut, txAdvice);
defaultPointcutAdvisor.setOrder(2);
return defaultPointcutAdvisor;
}
}