您现在的位置是:首页 > 文章详情

SpringBoot 注解事务声明式事务

日期:2018-11-29点击:602

springboot 对新人来说可能上手比springmvc要快,但是对于各位从springmvc转战到springboot的话,有些地方还需要适应下,尤其是xml配置。我个人是比较喜欢注解➕xml是因为看着方便,查找方便,清晰明了。但是xml完全可以使用注解代替,今天就扒一扒springboot中事务使用注解的玩法。


springboot的事务也主要分为两大类,一是xml声明式事务,二是注解事务,注解事务也可以实现类似声明式事务的方法,关于注解声明式事务,目前网上搜索不到合适的资料,所以在这里,我将自己查找和总结的几个方法写到这里,大家共同探讨


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(),事物会失效,具体原因暂时不明,如果各位有明白的,可以指点我下。

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 

原文链接:https://blog.roncoo.com/article/129836
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章