package com.aidijing.config; import lombok.Getter; import lombok.Setter; import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource; import org.springframework.transaction.interceptor.RollbackRuleAttribute; import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute; import org.springframework.transaction.interceptor.TransactionInterceptor; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; /** * @author : 披荆斩棘 * @date : 2017/9/8 */ @Setter @Getter @Configuration @ConfigurationProperties( prefix = "aidijing.transactional" ) public class TransactionalConfig { private static final String CUSTOMIZE_TRANSACTION_INTERCEPTOR_NAME = "customizeTransactionInterceptor"; private static final String DATA_SOURCE_SWITCH_METHOD_INTERCEPTOR_NAME = "dataSourceSwitchMethodInterceptor"; /** * 默认只对 "*Service" , "*ServiceImpl" Bean 进行事务处理,"*"表示模糊匹配, 比如 : userService,orderServiceImpl */ private static final String[] DEFAULT_TRANSACTION_BEAN_NAMES = { "*Service" , "*ServiceImpl" }; /** * 可传播事务配置 */ private static final String[] DEFAULT_REQUIRED_METHOD_RULE_TRANSACTION_ATTRIBUTES = { "add*" , "save*" , "insert*" , "delete*" , "update*" , "edit*" , "batch*" , "create*" , "remove*" , }; /** * 默认的只读事务 */ private static final String[] DEFAULT_READ_ONLY_METHOD_RULE_TRANSACTION_ATTRIBUTES = { "get*" , "count*" , "find*" , "query*" , "select*" , "list*" , "*" , }; /** * 自定义事务 BeanName 拦截 */ private String[] customizeTransactionBeanNames = {}; /** * 自定义方法名的事务属性相关联,可以使用通配符(*)字符关联相同的事务属性的设置方法; 只读事务 */ private String[] customizeReadOnlyMethodRuleTransactionAttributes = {}; /** * 自定义方法名的事务属性相关联,可以使用通配符(*)字符关联相同的事务属性的设置方法; * 传播事务(默认的){@link org.springframework.transaction.annotation.Propagation#REQUIRED} */ private String[] customizeRequiredMethodRuleTransactionAttributes = {}; /** * 配置事务拦截器 * * @param transactionManager : 事务管理器 * @return */ @Bean( CUSTOMIZE_TRANSACTION_INTERCEPTOR_NAME ) public TransactionInterceptor customizeTransactionInterceptor ( PlatformTransactionManager transactionManager ) { NameMatchTransactionAttributeSource transactionAttributeSource = new NameMatchTransactionAttributeSource(); RuleBasedTransactionAttribute readOnly = this.readOnlyTransactionRule(); RuleBasedTransactionAttribute required = this.requiredTransactionRule(); // 默认的只读事务配置 for ( String methodName : DEFAULT_READ_ONLY_METHOD_RULE_TRANSACTION_ATTRIBUTES ) { transactionAttributeSource.addTransactionalMethod( methodName , readOnly ); } // 默认的传播事务配置 for ( String methodName : DEFAULT_REQUIRED_METHOD_RULE_TRANSACTION_ATTRIBUTES ) { transactionAttributeSource.addTransactionalMethod( methodName , required ); } // 定制的只读事务配置 for ( String methodName : customizeReadOnlyMethodRuleTransactionAttributes ) { transactionAttributeSource.addTransactionalMethod( methodName , readOnly ); } // 定制的传播事务配置 for ( String methodName : customizeRequiredMethodRuleTransactionAttributes ) { transactionAttributeSource.addTransactionalMethod( methodName , required ); } return new TransactionInterceptor( transactionManager , transactionAttributeSource ); } /** * 配置事务 AOP 切入点 * {@link DataSourceSwitch} * * @param transactionInterceptor : {@link #customizeTransactionInterceptor(PlatformTransactionManager)} @Bean public AspectJExpressionPointcutAdvisor aspectJExpressionPointcutAdvisor ( @Qualifier( "customizeTransactionInterceptor" ) TransactionInterceptor transactionInterceptor ) { AspectJExpressionPointcutAdvisor pointcut = new AspectJExpressionPointcutAdvisor(); pointcut.setAdvice( transactionInterceptor ); pointcut.setExpression( "execution (* com.aidijing.*.*service.*.*(..))" ); return pointcut; } */ /** * {@link #dataSourceSwitchMethodInterceptor()} * {@link #customizeTransactionInterceptor(PlatformTransactionManager)} * * @return */ @Bean public BeanNameAutoProxyCreator beanNameAutoProxyCreator () { BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator(); beanNameAutoProxyCreator.setInterceptorNames( DATA_SOURCE_SWITCH_METHOD_INTERCEPTOR_NAME , CUSTOMIZE_TRANSACTION_INTERCEPTOR_NAME ); List< String > transactionBeanNames = new ArrayList<>( DEFAULT_TRANSACTION_BEAN_NAMES.length + customizeTransactionBeanNames.length ); // 默认 transactionBeanNames.addAll( Arrays.asList( DEFAULT_TRANSACTION_BEAN_NAMES ) ); // 定制 transactionBeanNames.addAll( Arrays.asList( customizeTransactionBeanNames ) ); // 归集 for ( String transactionBeanName : transactionBeanNames ) { beanNameAutoProxyCreator.setBeanNames( transactionBeanName ); } beanNameAutoProxyCreator.setProxyTargetClass( true ); return beanNameAutoProxyCreator; } @Bean( DATA_SOURCE_SWITCH_METHOD_INTERCEPTOR_NAME ) public DataSourceSwitchMethodInterceptor dataSourceSwitchMethodInterceptor () { return new DataSourceSwitchMethodInterceptor(); } /** * 支持当前事务;如果不存在创建一个新的 */ private RuleBasedTransactionAttribute requiredTransactionRule () { RuleBasedTransactionAttribute required = new RuleBasedTransactionAttribute(); required.setRollbackRules( Collections.singletonList( new RollbackRuleAttribute( Exception.class ) ) ); required.setPropagationBehavior( TransactionDefinition.PROPAGATION_REQUIRED ); required.setTimeout( TransactionDefinition.TIMEOUT_DEFAULT ); return required; } /** * 只读事务 */ private RuleBasedTransactionAttribute readOnlyTransactionRule () { RuleBasedTransactionAttribute readOnly = new RuleBasedTransactionAttribute(); readOnly.setReadOnly( true ); readOnly.setPropagationBehavior( TransactionDefinition.PROPAGATION_NOT_SUPPORTED ); return readOnly; } }