首页 > 编程 > Java > 正文

SpringBoot 注解事务声明式事务的方式

2019-11-26 11:31:40
字体:
来源:转载
供稿:网友

 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")@SpringBootApplicationpublic 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 事务依然生效@Configurationpublic 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 事务依然生效@Configurationpublic 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@Configurationpublic 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,使你的代码远离配置文件。

总结

以上所述是小编给大家介绍的SpringBoot 注解事务声明式事务的方式,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对武林网网站的支持!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表