首页 文章资讯内容详情

SpringBoot 注解事务声明式事务

2026-06-01 4 花语

本文内容纲要:

文章来源: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的配置如下

<?xmlversion="1.0"encoding="UTF-8"?> <beansxmlns="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"> <beanid="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <propertyname="dataSource"ref="dataSource"></property> </bean> <tx:adviceid="cftxAdvice"transaction-manager="txManager"> <tx:attributes> <tx:methodname="query*"propagation="SUPPORTS"read-only="true"></tx:method> <tx:methodname="get*"propagation="SUPPORTS"read-only="true"></tx:method> <tx:methodname="select*"propagation="SUPPORTS"read-only="true"></tx:method> <tx:methodname="*"propagation="REQUIRED"rollback-for="Exception"></tx:method> </tx:attributes> </tx:advice> <aop:config> <aop:pointcutid="allManagerMethod"expression="execution(*com.exmaple.fm..service.*.*(..))"/> <aop:advisoradvice-ref="txAdvice"pointcut-ref="allManagerMethod"order="0"/> </aop:config> </beans>

springboot启动类如下:

packagecom.example.fm; importorg.springframework.boot.SpringApplication; importorg.springframework.boot.autoconfigure.SpringBootApplication; importorg.springframework.context.annotation.ImportResource; @ImportResource("classpath:transaction.xml") @SpringBootApplication publicclassApplication{ publicstaticvoidmain(String[]args){ SpringApplication.run(Application.class,args); } }

启动后即可开启事务,不过项目里导入了xml配置,如果不想导入xml配置,可以使用注解的方式。

springboot之注解事务

注解事务讲解之前,需要先了解下spring创建代理的几个类,在spring内部,是通过BeanPostProcessor来完成自动创建代理工作的。BeanPostProcessor接口的实现只是在ApplicationContext初始化的时候才会自动加载,而普通的BeanFactory只能通过编程的方式调用之。根据匹配规则的不同大致分为三种类别:

a、匹配Bean的名称自动创建匹配到的Bean的代理,实现类BeanNameAutoProxyCreator

<beanid="testInterceptor"class="com.example.service.config.testInerceptor”></bean> <beanid="profileAutoProxyCreator"class="org.springframework.aop.framework. autoproxy.BeanNameAutoProxyProxyCreator"> <bean> <propertyname="beanNames"> <list> <value>*Service</value> </list> </property> <propertyname="interceptorNames"> <value>testInterceptor</value> </property> </bean>

b、根据Bean中的AspectJ注解自动创建代理,实现类AnnotationAwareAspectJAutoProxyCreator

<aop:aspectj-autoproxyproxy-target-class="true"/> <beanid="annotationAwareAspectJAutoProxyCreatorTest"class="com.example.service.AnnotationAwareAspectJAutoProxyCreatorTest"/> <aop:config> <aop:aspectref="annotationAwareAspectJAutoProxyCreatorTest"> <aop:aroundmethod="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事务都可以生效

packagecom.exmple.service.fm9.config; importjava.util.Collections; importjava.util.HashMap; importjava.util.Map; importorg.aspectj.lang.annotation.Aspect; importorg.springframework.aop.Advisor; importorg.springframework.aop.aspectj.AspectJExpressionPointcut; importorg.springframework.aop.support.DefaultPointcutAdvisor; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importorg.springframework.stereotype.Component; importorg.springframework.transaction.PlatformTransactionManager; importorg.springframework.transaction.TransactionDefinition; importorg.springframework.transaction.interceptor.NameMatchTransactionAttributeSource; importorg.springframework.transaction.interceptor.RollbackRuleAttribute; importorg.springframework.transaction.interceptor.RuleBasedTransactionAttribute; importorg.springframework.transaction.interceptor.TransactionAttribute; importorg.springframework.transaction.interceptor.TransactionInterceptor; /** *Createdbyguozpon2017/8/28. */ @Aspect //@Component事务依然生效 @Configuration publicclassTxAdviceInterceptor{ privatestaticfinalintTX_METHOD_TIMEOUT=5; privatestaticfinalStringAOP_POINTCUT_EXPRESSION="execution(*com.alibaba.fm9..service.*.*(..))"; @Autowired privatePlatformTransactionManagertransactionManager; @Bean publicTransactionInterceptortxAdvice(){ NameMatchTransactionAttributeSourcesource=newNameMatchTransactionAttributeSource(); /*只读事务,不做更新操作*/ RuleBasedTransactionAttributereadOnlyTx=newRuleBasedTransactionAttribute(); readOnlyTx.setReadOnly(true); readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED); /*当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务*/ RuleBasedTransactionAttributerequiredTx=newRuleBasedTransactionAttribute(); requiredTx.setRollbackRules( Collections.singletonList(newRollbackRuleAttribute(Exception.class))); requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); requiredTx.setTimeout(TX_METHOD_TIMEOUT); Map<String,TransactionAttribute>txMap=newHashMap<>(); 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); TransactionInterceptortxAdvice=newTransactionInterceptor(transactionManager,source); returntxAdvice; } @Bean publicAdvisortxAdviceAdvisor(){ AspectJExpressionPointcutpointcut=newAspectJExpressionPointcut(); pointcut.setExpression(AOP_POINTCUT_EXPRESSION); returnnewDefaultPointcutAdvisor(pointcut,txAdvice()); //returnnewDefaultPointcutAdvisor(pointcut,txAdvice); } }

b.方式1,这里使用Component或Configuration事务都可以生效

packagecom.exmple.service.fm9.config; importjava.util.Collections; importjava.util.HashMap; importjava.util.Map; importorg.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importorg.springframework.stereotype.Component; importorg.springframework.transaction.PlatformTransactionManager; importorg.springframework.transaction.TransactionDefinition; importorg.springframework.transaction.interceptor.NameMatchTransactionAttributeSource; importorg.springframework.transaction.interceptor.RollbackRuleAttribute; importorg.springframework.transaction.interceptor.RuleBasedTransactionAttribute; importorg.springframework.transaction.interceptor.TransactionAttribute; importorg.springframework.transaction.interceptor.TransactionAttributeSource; importorg.springframework.transaction.interceptor.TransactionInterceptor; /** *Createdbyguozpon2017/8/29. */ //@Component事务依然生效 @Configuration publicclassTxAnoConfig{ /*事务拦截类型*/ @Bean("txSource") publicTransactionAttributeSourcetransactionAttributeSource(){ NameMatchTransactionAttributeSourcesource=newNameMatchTransactionAttributeSource(); /*只读事务,不做更新操作*/ RuleBasedTransactionAttributereadOnlyTx=newRuleBasedTransactionAttribute(); readOnlyTx.setReadOnly(true); readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED); /*当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务*/ //RuleBasedTransactionAttributerequiredTx=newRuleBasedTransactionAttribute(); //requiredTx.setRollbackRules( //Collections.singletonList(newRollbackRuleAttribute(Exception.class))); //requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); RuleBasedTransactionAttributerequiredTx=newRuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, Collections.singletonList(newRollbackRuleAttribute(Exception.class))); requiredTx.setTimeout(5); Map<String,TransactionAttribute>txMap=newHashMap<>(); 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); returnsource; } /**切面拦截规则参数会自动从容器中注入*/ @Bean publicAspectJExpressionPointcutAdvisorpointcutAdvisor(TransactionInterceptortxInterceptor){ AspectJExpressionPointcutAdvisorpointcutAdvisor=newAspectJExpressionPointcutAdvisor(); pointcutAdvisor.setAdvice(txInterceptor); pointcutAdvisor.setExpression("execution(*com.alibaba.fm9..service.*.*(..))"); returnpointcutAdvisor; } /*事务拦截器*/ @Bean("txInterceptor") TransactionInterceptorgetTransactionInterceptor(PlatformTransactionManagertx){ returnnewTransactionInterceptor(tx,transactionAttributeSource()); } }

c.方式1,这里使用Component或Configuration事务都可以生效

packagecom.exmple.service.fm9.config; importjava.util.Properties; importorg.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importorg.springframework.jdbc.datasource.DataSourceTransactionManager; importorg.springframework.stereotype.Component; importorg.springframework.transaction.interceptor.TransactionInterceptor; /** *Createdbyguozpon2017/8/28. * */ //@Component @Configuration publicclassTxConfigBeanName{ @Autowired privateDataSourceTransactionManagertransactionManager; //创建事务通知 @Bean(name="txAdvice") publicTransactionInterceptorgetAdvisor()throwsException{ Propertiesproperties=newProperties(); 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"); TransactionInterceptortsi=newTransactionInterceptor(transactionManager,properties); returntsi; } @Bean publicBeanNameAutoProxyCreatortxProxy(){ BeanNameAutoProxyCreatorcreator=newBeanNameAutoProxyCreator(); creator.setInterceptorNames("txAdvice"); creator.setBeanNames("*Service","*ServiceImpl"); creator.setProxyTargetClass(true); returncreator; } }

d.方式1,这里使用Component或Configuration并不是所有事务都可以生效,例如Configuration的时候如果打开注释部分的而且不把代码都移动到defaultPointcutAdvisor(),事物会失效,具体原因暂时不明,如果各位有明白的,可以指点我下。

初始使用:

packagecom.alibaba.fm9.config; importjava.util.Properties; importjavax.sql.DataSource; importorg.springframework.aop.aspectj.AspectJExpressionPointcut; importorg.springframework.aop.support.DefaultPointcutAdvisor; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importorg.springframework.jdbc.datasource.DataSourceTransactionManager; importorg.springframework.stereotype.Component; importorg.springframework.transaction.interceptor.TransactionInterceptor; /** *Createdbyguozpon2017/8/28.?? */ @Component //@Configuration事务失败 publicclassTxOtherConfigDefault{ @Autowired privateDataSourcedataSource; //@Bean //@ConditionalOnMissingBean publicPlatformTransactionManagerannotationDrivenTransactionManager(){ returnnewDataSourceTransactionManager(dataSource); }*/ @Autowired privateDataSourceTransactionManagertransactionManager; @Bean publicTransactionInterceptortransactionInterceptor(){ Propertiesattributes=newProperties(); attributes.setProperty("get*","PROPAGATION_REQUIRED"); attributes.setProperty("add*","PROPAGATION_REQUIRED"); attributes.setProperty("update*","PROPAGATION_REQUIRED"); attributes.setProperty("delete*","PROPAGATION_REQUIRED"); TransactionInterceptortxAdvice=newTransactionInterceptor(transactionManager,attributes); returntxAdvice; } @Bean publicAspectJExpressionPointcutaspectJExpressionPointcut(){ AspectJExpressionPointcutpointcut=newAspectJExpressionPointcut(); StringtransactionExecution="execution(*com.alibaba.fm9..service.*.*(..))"; pointcut.setExpression(transactionExecution); returnpointcut; } @Bean publicDefaultPointcutAdvisordefaultPointcutAdvisor(){ DefaultPointcutAdvisoradvisor=newDefaultPointcutAdvisor(); advisor.setPointcut(aspectJExpressionPointcut()); advisor.setAdvice(transactionInterceptor()); returnadvisor; } }

后修改如下:

ackagecom.alibaba.fm9.config; importjava.util.Properties; importjavax.sql.DataSource; importorg.springframework.aop.aspectj.AspectJExpressionPointcut; importorg.springframework.aop.support.DefaultPointcutAdvisor; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importorg.springframework.jdbc.datasource.DataSourceTransactionManager; importorg.springframework.stereotype.Component; importorg.springframework.transaction.PlatformTransactionManager; importorg.springframework.transaction.interceptor.TransactionInterceptor; /** *Createdbyguozpon2017/8/28. *??????? */ @Configuration//事务失效,都移动到一个方法不失效 //@Component//事务可行,不用都移动到一个方法 publicclassTxOtherConfigDefaultBean{ publicstaticfinalStringtransactionExecution="execution(*com.alibaba.fm9..service.*.*(..))"; @Autowired privatePlatformTransactionManagertransactionManager; //@Bean //@ConditionalOnMissingBean //publicPlatformTransactionManagertransactionManager(){ //returnnewDataSourceTransactionManager(dataSource); //} @Bean publicTransactionInterceptortransactionInterceptor(){ Propertiesattributes=newProperties(); attributes.setProperty("get*","PROPAGATION_REQUIRED,-Exception"); attributes.setProperty("add*","PROPAGATION_REQUIRED,-Exception"); attributes.setProperty("update*","PROPAGATION_REQUIRED,-Exception"); attributes.setProperty("delete*","PROPAGATION_REQUIRED,-Exception"); //TransactionInterceptortxAdvice=newTransactionInterceptor(transactionManager(),attributes); TransactionInterceptortxAdvice=newTransactionInterceptor(transactionManager,attributes); returntxAdvice; } //@Bean //publicAspectJExpressionPointcutaspectJExpressionPointcut(){ //AspectJExpressionPointcutpointcut=newAspectJExpressionPointcut(); //pointcut.setExpression(transactionExecution); //returnpointcut; //} @Bean publicDefaultPointcutAdvisordefaultPointcutAdvisor(){ //AspectJExpressionPointcutpointcut=newAspectJExpressionPointcut(); //pointcut.setExpression(transactionExecution); //DefaultPointcutAdvisoradvisor=newDefaultPointcutAdvisor(); //advisor.setPointcut(pointcut); //advisor.setAdvice(transactionInterceptor()); AspectJExpressionPointcutpointcut=newAspectJExpressionPointcut(); pointcut.setExpression(transactionExecution); DefaultPointcutAdvisoradvisor=newDefaultPointcutAdvisor(); advisor.setPointcut(pointcut); Propertiesattributes=newProperties(); attributes.setProperty("get*","PROPAGATION_REQUIRED,-Exception"); attributes.setProperty("add*","PROPAGATION_REQUIRED,-Exception"); attributes.setProperty("update*","PROPAGATION_REQUIRED,-Exception"); attributes.setProperty("delete*","PROPAGATION_REQUIRED,-Exception"); TransactionInterceptortxAdvice=newTransactionInterceptor(transactionManager,attributes); advisor.setAdvice(txAdvice); returnadvisor; } }

简单来说,springboot使用上述注解的几种方式开启事物,可以达到和xml中声明的同样效果,但是却告别了xml,使你的代码远离配置文件。

如果有错误的地方,望各位指正。如有其它问题,可以联系

文章来源:http://www.cnblogs.com/guozp/articles/7446477.html

本文内容总结:

原文链接:https://www.cnblogs.com/guozp/p/7446477.html