Spring注解配置全局自定义@Transactional 属性
来源:互联网 发布:软件架构师培训 编辑:程序博客网 时间:2024/05/23 21:49
背景
自从使用Spring4以来,基本已抛弃使用xml方式的配置,完全使用更方便的@Configuration方式,这时有些原先使用xml定义的配置都要找对应的注解方式重新配置。最近一个新项目需要使用到自定义XXXException(非RuntimeException)来控制事务回滚,而Spring事务默认是对RuntimeException/Error才进行回滚,如果需要对其它Exception执行回滚则一般是在@Transactional中设置属性rollbackForXXX、noRollbackForXXX来控制。但对于一般项目来说这些规则都是一致的,能找到一个全局配置的方式是最好的。
分析
通过查看Spring源代码 TransactionAspectSupport.completeTransactionAfterThrowing (被主方法invokeWithinTransaction调用),transactionAttribute的内容是关键,实际其实现类为RuleBasedTransactionAttribute,剩下的问题就是如何自定义修改这个类的内容了。
/** * Handle a throwable, completing the transaction. * We may commit or roll back, depending on the configuration. * @param txInfo information about the current transaction * @param ex throwable encountered */ 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); } // 这里是判断是否进行Rollback的关键 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; } } } }
解决方案
一、添加自定义设置Transaction属性类
- 新增CustomAnnotationTransactionAttributeSource继承 AnnotationTransactionAttributeSource,覆盖方法determineTransactionAttribute。
- 参考如下,TransactionAttribute 强制转换为RuleBasedTransactionAttribute 即可设置各属性
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) { if (ae.getAnnotations().length > 0) { for (TransactionAnnotationParser annotationParser : this.annotationParsers) { TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae); if (attr != null) { // 强制转成RuleBasedTransactionAttribute ,并设置 RuleBasedTransactionAttribute RuleBaseAttr = (RuleBasedTransactionAttribute )attr; List<RollbackRuleAttribute> rollbackRules = RuleBaseAttr.getRollbackRules(); for (RollbackRuleAttribute rbra : rollbackRules ){ if ( ! "xxx.xxx.XXXException".equals(rbra.getExceptionName()){ // 不包含自定义的XXXException时,做处理,如添加: // rollbackRules.add(new RollbackRuleAttribute(XXXException.class)); } } //... 修改内容,如: //Class<?>[] rbf = attributes.getClassArray("rollbackFor"); for (Class<?> rbRule : rbf) { RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule); rollBackRules.add(rule); } return attr; } } } return null;}
- 其他具体属性可以参考SpringTransactionAnnotationParser.parseTransactionAnnotation的使用
二、添加Spring 加载后置处理器
前面完成了自定义设置类,然后我们希望它可以在spring加载完所有bean之后执行,这时又可以使用Spring 加载后置处理器这一神器了,具体实现如下:
@Beanpublic class XXXXXX implements BeanFactoryPostProcessor { public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException { String[] names = factory.getBeanNamesForType(AnnotationTransactionAttributeSource.class); for (String name: names) { BeanDefinition bd = factory.getBeanDefinition(name); bd.setBeanClassName("xxxxxx.CustomAnnotationTransactionAttributeSource"); } }}
至此基本的方式已经成型,至于通过具体文件配置之类的就需要其它额外工作了。
阅读全文
0 0
- Spring注解配置全局自定义@Transactional 属性
- Spring的@Transactional注解的rollbackFor属性
- 【Spring】spring@Transactional注解
- @Transactional 注解的属性
- Spring 注解@Transactional
- spring 事务注解@Transactional
- spring 事务注解@Transactional
- Spring 注解@Transactional
- Spring 注解@Transactional
- spring 事务注解@Transactional
- Spring 注解@Transactional
- Spring 注解 之 @Transactional
- Spring 注解@Transactional
- Spring 注解@Transactional详解
- Spring @Transactional注解
- spring @Transactional 注解
- Spring注解事务@Transactional
- spring @Transactional 注解学习
- 如何在FPGA中利用Verilog实现任意倍的奇数分频
- 【C++】学习笔记四十四——单独编译
- 【Codeforces 814 C. An impassioned circulation of affection】+ 尺取法
- 第十六周:(Sicily) Huffman Coding V1(c++)
- iSCSI远程块存储
- Spring注解配置全局自定义@Transactional 属性
- ThinkPHP5学习(12)模型和关联
- cv2.error: The node does not represent a user object (unknown type?) python+opencv
- HTML学习笔记day one
- 分散读取以及聚集写入
- android dagger2搭建mvp架构
- 网络框架解析
- synchronized关键字实现同步
- Microsoft Office 批量授权版下载链接