SpringBoot 注解事务声明式事务
文章来源: http://www.cnblogs.com/guozp/articles/7446477.html
springboot 对新人来说可能上手比springmvc要快,但是对于各位从springmvc转战到springboot的话,有些地方还需要适应下,尤其是xml配置。我个人是比较喜欢注解➕xml是因为看着方便,查找方便,清晰明了。但是xml完全可以使用注解代替,今天就扒一扒springboot中事务使用注解的玩法。
springboot的事务也主要分为两大类,一是xml声明式事务,二是注解事务,注解事务也可以实现类似声明式事务的方法,关于注解声明式事务,目前网上搜索不到合适的资料,所以在这里,我将自己查找和总结的几个方法写到这里,大家共同探讨
文章来源: http://www.cnblogs.com/guozp/articles/7446477.html
- springboot 之 xml事务
可以使用 @ImportResource("classpath:transaction.xml") 引入该xml的配置,xml的配置如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" ></property>
</bean>
<tx:advice id="cftxAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="query*" propagation="SUPPORTS" read-only="true" ></tx:method>
<tx:method name="get*" propagation="SUPPORTS" read-only="true" ></tx:method>
<tx:method name="select*" propagation="SUPPORTS" read-only="true" ></tx:method>
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception" ></tx:method>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="allManagerMethod" expression="execution (* com.exmaple.fm..service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod" order="0" />
</aop:config> </beans>
springboot 启动类如下:
package com.example.fm; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource; @ImportResource("classpath:transaction.xml")
@SpringBootApplication
public class Application { public static void main(String[] args) {
SpringApplication.run(Application.class, args);
} }
启动后即可开启事务,不过项目里导入了xml配置,如果不想导入xml配置,可以使用注解的方式。
- springboot 之 注解事务
注解事务讲解之前,需要先了解下spring创建代理的几个类,在spring内部,是通过BeanPostProcessor来完成自动创建代理工作的。BeanPostProcessor接口的实现只是在ApplicationContext初始化的时候才会自动加载,而普通的BeanFactory只能通过编程的方式调用之。根据 匹配规则的不同大致分为三种类别:
a、匹配Bean的名称自动创建匹配到的Bean的代理,实现类BeanNameAutoProxyCreator
<bean id="testInterceptor" class="com.example.service.config.testInerceptor”></bean> <bean id="profileAutoProxyCreator" class="org.springframework.aop.framework.
autoproxy.BeanNameAutoProxyProxyCreator">
<bean>
<property name="beanNames">
<list>
<value>*Service</value>
</list>
</property>
<property name="interceptorNames">
<value> testInterceptor </value>
</property>
</bean>
b、根据Bean中的AspectJ注解自动创建代理,实现类AnnotationAwareAspectJAutoProxyCreator
<aop:aspectj-autoproxy proxy-target-class="true"/> <bean id="annotationAwareAspectJAutoProxyCreatorTest" class="com.example.service.AnnotationAwareAspectJAutoProxyCreatorTest"/>
<aop:config>
<aop:aspect ref="annotationAwareAspectJAutoProxyCreatorTest">
<aop:around method="process" pointcut="execution (* com.example.service.fm..*.*(..))"/>
</aop:aspect>
</aop:config>
c、根据Advisor的匹配机制自动创建代理,会对容器中所有的Advisor进行扫描,自动将这些切面应用到匹配的Bean中,实现类DefaultAdvisorAutoProxyCreator
接下来开讲注解开启事务的方法:
1、Transactional注解事务
需要在进行事物管理的方法上添加注解@Transactional,或者偷懒的话直接在类上面添加该注解,使得所有的方法都进行事物的管理,但是依然需要在需要事务管理的类上都添加,工作量比较大,这里只是简单说下,具体的可以google或者bing
2、注解声明式事务
Component或Configuration中bean的区别,有时间我会专门写一篇来讲解下
a.方式1,这里使用Component或Configuration事务都可以生效
package com.exmple.service.fm9.config; import java.util.Collections;
import java.util.HashMap;
import java.util.Map; 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.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
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.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor; /**
* Created by guozp on 2017/8/28.
*/
@Aspect
//@Component 事务依然生效
@Configuration
public class TxAdviceInterceptor { private static final int TX_METHOD_TIMEOUT = 5;
private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.alibaba.fm9..service.*.*(..))"; @Autowired
private PlatformTransactionManager transactionManager; @Bean
public TransactionInterceptor txAdvice() {
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
/*只读事务,不做更新操作*/
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(TX_METHOD_TIMEOUT);
Map<String, TransactionAttribute> txMap = new HashMap<>();
txMap.put("add*", requiredTx);
txMap.put("save*", requiredTx);
txMap.put("insert*", requiredTx);
txMap.put("update*", requiredTx);
txMap.put("delete*", requiredTx);
txMap.put("get*", readOnlyTx);
txMap.put("query*", readOnlyTx);
source.setNameMap( txMap );
TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, source);
return txAdvice;
} @Bean
public Advisor txAdviceAdvisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
return new DefaultPointcutAdvisor(pointcut, txAdvice());
//return new DefaultPointcutAdvisor(pointcut, txAdvice);
}
}
b.方式1,这里使用Component或Configuration事务都可以生效
package com.exmple.service.fm9.config; import java.util.Collections;
import java.util.HashMap;
import java.util.Map; import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
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.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor; /**
* Created by guozp on 2017/8/29.
*/
//@Component 事务依然生效
@Configuration
public class TxAnoConfig {
/*事务拦截类型*/
@Bean("txSource")
public TransactionAttributeSource transactionAttributeSource(){
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
/*只读事务,不做更新操作*/
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);
RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED,
Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
requiredTx.setTimeout(5);
Map<String, TransactionAttribute> txMap = new HashMap<>();
txMap.put("add*", requiredTx);
txMap.put("save*", requiredTx);
txMap.put("insert*", requiredTx);
txMap.put("update*", requiredTx);
txMap.put("delete*", requiredTx);
txMap.put("get*", readOnlyTx);
txMap.put("query*", readOnlyTx);
source.setNameMap( txMap ); return source;
} /**切面拦截规则 参数会自动从容器中注入*/
@Bean
public AspectJExpressionPointcutAdvisor pointcutAdvisor(TransactionInterceptor txInterceptor){
AspectJExpressionPointcutAdvisor pointcutAdvisor = new AspectJExpressionPointcutAdvisor();
pointcutAdvisor.setAdvice(txInterceptor);
pointcutAdvisor.setExpression("execution (* com.alibaba.fm9..service.*.*(..))");
return pointcutAdvisor;
} /*事务拦截器*/
@Bean("txInterceptor")
TransactionInterceptor getTransactionInterceptor(PlatformTransactionManager tx){
return new TransactionInterceptor(tx , transactionAttributeSource()) ;
}
}
c.方式1,这里使用Component或Configuration事务都可以生效
package com.exmple.service.fm9.config; import java.util.Properties; import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.interceptor.TransactionInterceptor; /**
* Created by guozp on 2017/8/28.
*
*/
//@Component
@Configuration
public class TxConfigBeanName { @Autowired
private DataSourceTransactionManager transactionManager; // 创建事务通知 @Bean(name = "txAdvice")
public TransactionInterceptor getAdvisor() throws Exception { Properties properties = new Properties();
properties.setProperty("get*", "PROPAGATION_REQUIRED,-Exception,readOnly");
properties.setProperty("add*", "PROPAGATION_REQUIRED,-Exception,readOnly");
properties.setProperty("save*", "PROPAGATION_REQUIRED,-Exception,readOnly");
properties.setProperty("update*", "PROPAGATION_REQUIRED,-Exception,readOnly");
properties.setProperty("delete*", "PROPAGATION_REQUIRED,-Exception,readOnly"); TransactionInterceptor tsi = new TransactionInterceptor(transactionManager,properties);
return tsi; } @Bean
public BeanNameAutoProxyCreator txProxy() {
BeanNameAutoProxyCreator creator = new BeanNameAutoProxyCreator();
creator.setInterceptorNames("txAdvice");
creator.setBeanNames("*Service", "*ServiceImpl");
creator.setProxyTargetClass(true);
return creator;
}
}
d.方式1,这里使用Component或Configuration并不是所有事务都可以生效,例如Configuration的时候如果打开注释部分的而且不把代码都移动到 defaultPointcutAdvisor(),事物会失效,具体原因暂时不明,如果各位有明白的,可以指点我下。
初始使用:
package com.alibaba.fm9.config; import java.util.Properties; import javax.sql.DataSource; import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.interceptor.TransactionInterceptor; /**
* Created by guozp on 2017/8/28. ??
*/
@Component
//@Configuration 事务失败
public class TxOtherConfigDefault { @Autowired
private DataSource dataSource; //@Bean
//@ConditionalOnMissingBean
public PlatformTransactionManager annotationDrivenTransactionManager() {
return new DataSourceTransactionManager(dataSource);
}*/ @Autowired
private DataSourceTransactionManager transactionManager; @Bean
public TransactionInterceptor transactionInterceptor() {
Properties attributes = new Properties();
attributes.setProperty("get*", "PROPAGATION_REQUIRED");
attributes.setProperty("add*", "PROPAGATION_REQUIRED");
attributes.setProperty("update*", "PROPAGATION_REQUIRED");
attributes.setProperty("delete*", "PROPAGATION_REQUIRED");
TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, attributes);
return txAdvice;
} @Bean
public AspectJExpressionPointcut aspectJExpressionPointcut(){
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
String transactionExecution = "execution (* com.alibaba.fm9..service.*.*(..))";
pointcut.setExpression(transactionExecution);
return pointcut;
} @Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor(){
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
advisor.setPointcut(aspectJExpressionPointcut());
advisor.setAdvice(transactionInterceptor());
return advisor;
}
}
后修改如下:
ackage com.alibaba.fm9.config; import java.util.Properties; import javax.sql.DataSource; import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.interceptor.TransactionInterceptor; /**
* Created by guozp on 2017/8/28.
* ???????
*/
@Configuration //事务失效,都移动到一个方法不失效
//@Component // 事务可行,不用都移动到一个方法
public class TxOtherConfigDefaultBean { public static final String transactionExecution = "execution (* com.alibaba.fm9..service.*.*(..))"; @Autowired
private PlatformTransactionManager transactionManager; //@Bean
//@ConditionalOnMissingBean
//public PlatformTransactionManager transactionManager() {
// return new DataSourceTransactionManager(dataSource);
//} @Bean
public TransactionInterceptor transactionInterceptor() {
Properties attributes = new Properties();
attributes.setProperty("get*", "PROPAGATION_REQUIRED,-Exception");
attributes.setProperty("add*", "PROPAGATION_REQUIRED,-Exception");
attributes.setProperty("update*", "PROPAGATION_REQUIRED,-Exception");
attributes.setProperty("delete*", "PROPAGATION_REQUIRED,-Exception");
//TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager(), attributes);
TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, attributes);
return txAdvice;
} //@Bean
//public AspectJExpressionPointcut aspectJExpressionPointcut(){
// AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
// pointcut.setExpression(transactionExecution);
// return pointcut;
//} @Bean
public DefaultPointcutAdvisor defaultPointcutAdvisor(){
//AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
//pointcut.setExpression(transactionExecution);
//DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
//advisor.setPointcut(pointcut);
//advisor.setAdvice(transactionInterceptor());
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(transactionExecution);
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
advisor.setPointcut(pointcut);
Properties attributes = new Properties();
attributes.setProperty("get*", "PROPAGATION_REQUIRED,-Exception");
attributes.setProperty("add*", "PROPAGATION_REQUIRED,-Exception");
attributes.setProperty("update*", "PROPAGATION_REQUIRED,-Exception");
attributes.setProperty("delete*", "PROPAGATION_REQUIRED,-Exception");
TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, attributes);
advisor.setAdvice(txAdvice);
return advisor;
}
}
简单来说,springboot使用上述注解的几种方式开启事物,可以达到和xml中声明的同样效果,但是却告别了xml,使你的代码远离配置文件。
如果有错误的地方,望各位指正。如有其它问题,可以联系
文章来源: http://www.cnblogs.com/guozp/articles/7446477.html
SpringBoot 注解事务声明式事务的更多相关文章
- spring基于注解的声明式事务控制
package com.hope.service.impl;import com.hope.dao.IAccountDao;import com.hope.domain.Account;import ...
- 28Spring_的事务管理_银行转账业务加上事务控制_基于注解进行声明式事务管理
将applicationContext.xml 和 AccountServiceImpl 给备份一个取名为applicationContext2.xml 和 AccountServiceImpl2.j ...
- spring注解开发-声明式事务(源码)
1. 环境搭建与测试 1)导入相关依赖 数据源.数据库驱动.Spring-jdbc模块 <dependency> <groupId>org.springframework< ...
- 阶段3 2.Spring_10.Spring中事务控制_8 spring基于纯注解的声明式事务控制
新建项目 把之前项目src下的内容全部复制过来 pom.xml内复制过来 开始配置 新建一个config的包,然后再新建配置文件类SpringConfiguration @Configuration这 ...
- 阶段3 2.Spring_10.Spring中事务控制_7 spring基于注解的声明式事务控制
创建新项目 复制上一个pom.xml的内容.依赖和打包的方式 再复制src的代码过来 bean.xml.多导入context的声明 Service的实现类增加注解 dao的set方法删掉 通过Auto ...
- spring下春注解的声明式事务控制
package com.hope.test;import com.hope.domain.Account;import com.hope.service.IAccountService;import ...
- spring事物配置,声明式事务管理和基于@Transactional注解的使用
http://blog.csdn.net/bao19901210/article/details/41724355 http://www.cnblogs.com/leiOOlei/p/3725911. ...
- 事务之三:编程式事务、声明式事务(XML配置事务、注解实现事务)
Spring2.0框架的事务处理有两大类: JdbcTemplate操作采用的是JDBC默认的AutoCommit模式,也就是说我们还无法保证数据操作的原子性(要么全部生效,要么全部无效),如: Jd ...
- spring事务配置,声明式事务管理和基于@Transactional注解的使用(转载)
原文地址:http://blog.csdn.net/bao19901210/article/details/41724355 事务管理对于企业应用来说是至关重要的,好使出现异常情况,它也可以保证数据的 ...
随机推荐
- Reverse bits - 按位反转一个int型数字
Reverse bits of a given 32 bits unsigned integer. For example, given input 43261596 (represented in ...
- python数据结构链表之单向链表
单向链表 单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域.这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值. 表元素域ele ...
- [BZOJ 4832][lydsy 4月赛] 抵制克苏恩
题面贴一发 [Lydsy2017年4月月赛]抵制克苏恩 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 443 Solved: 164[Submit][ ...
- Mybatis框架分析
摘要 本篇文章只是个人阅读mybatis源码总结的经验或者个人理解mybatis的基本轮廓,作为抛砖引玉的功能,希望对你有帮助,如果需要深入了解细节还需亲自去阅读源码. mybatis基本架构 myb ...
- mysql忘记密码,修改密码重新安装的一些问题
前言 想要装cobra,却意外发现mysql连接失败,命令行连一下发现无论怎么样都连不上了. 我能想到的密码都用上了,糟糕!看来只能修改密码,或者重装了. 最后是重装搞定的,当然也发现了正确的修改密码 ...
- Python巡检Oracle表空间并邮件告警
最近,自学了Python基础,突发奇想,把以前通过shell自定义通过nagios实现Oracle表空间以及ASM以及备份的脚本改进下,首先感叹的是Python脚本看上去确实挺好的,效率还不错. 这是 ...
- Loadrunner错误 -27727: 下载资源时步骤下载超时 (120 seconds) 已过期
由于压力大了,下载资源所用时间就长了,可以设置加大超时时间 运行时设置 Internet 协议--首选项--高级--选项 --General--步骤下载超时(秒) 把这个值从120改为更大,如300, ...
- <Mastering KVM Virtualization>:第三章 搭建独立的KVM虚拟化
在第二章,你了解了KVM的内部结构:在本章中,您将了解如何将Linux服务器设置为虚拟化主机.我们正在讨论将KVM用于虚拟化并将libvirt作为虚拟化管理引擎. KVM开启了虚拟化并利用你的服务器或 ...
- Thinkphp5 用ab压力测试工具测试高并发请求
上篇文章[Thinkphp5实现悲观锁]已介绍过thinkphp5使用悲观锁实现高并发的场景,这篇文章将实际测试下. 在shell里进入到apache的bin目录,输入以下url: ab -n 100 ...
- 填涂颜色 洛谷 p1162
题目描述 由数字0 组成的方阵中,有一任意形状闭合圈,闭合圈由数字1构成,围圈时只走上下左右4个方向.现要求把闭合圈内的所有空间都填写成2.例如:6X6的方阵(n=6),涂色前和涂色后的方阵如下: 0 ...