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

 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,使你的代码远离配置文件。

总结

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

(0)

相关推荐

  • Spring事务传播属性和隔离级别详细介绍

    1 事务的传播属性(Propagation) 1) REQUIRED ,这个是默认的属性 Support a current transaction, create a new one if none exists. 如果存在一个事务,则支持当前事务.如果没有事务则开启一个新的事务. 被设置成这个级别时,会为每一个被调用的方法创建一个逻辑事务域.如果前面的方法已经创建了事务,那么后面的方法支持当前的事务,如果当前没有事务会重新建立事务. 2) MANDATORY Support a curren

  • 完美解决Spring声明式事务不回滚的问题

    疑问,确实像往常一样在service上添加了注解 @Transactional,为什么查询数据库时还是发现有数据不一致的情况,想想肯定是事务没起作用,出现异常的时候数据没有回滚.于是就对相关代码进行了一番测试,结果发现一下踩进了两个坑,确实是事务未回滚导致的数据不一致. 下面总结一下经验教训: Spring事务的管理操作方法 编程式的事务管理 实际应用中很少使用 通过使用TransactionTemplate 手动管理事务 声明式的事务管理 开发中推荐使用(代码侵入最少) Spring的声明式事

  • 详解在Spring Boot中使用数据库事务

    我们在前面已经分别介绍了如何在spring Boot中使用JPA以及如何在Spring Boot中输出REST资源.那么关于数据库访问还有一个核心操作那就是事务的处理了,前面两篇博客小伙伴们已经见识到Spring Boot带给我们的巨大便利了,其实不用猜,我们也知道Spring Boot在数据库事务处理问题上也给我们带来惊喜,OK,废话不多说,就来看看如何在Spring Boot中使用事务吧. OK,那我们开始今天愉快的coding旅程吧! 创建Project并添加数据库依赖 这个没啥好说的,不

  • Spring3.0配置多个事务管理器的方法

    Spring3.0配置多个事务管理器(即操作多个数据源)的方法 大多数项目只需要一个事务管理器.然而,有些项目为了提高效率.或者有多个完全不同又不相干的数据源,最好用多个事务管理器.机智的Spring的Transactional管理已经考虑到了这一点,首先分别定义多个transactional manager,并为qualifier属性指定不同的值:然后在需要使用@Transactional注解的时候指定TransactionManager的qualifier属性值或者直接使用bean名称.配置

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

    springboot 对新人来说可能上手比springmvc要快,但是对于各位从springmvc转战到springboot的话,有些地方还需要适应下,尤其是xml配置.我个人是比较喜欢注解➕xml是因为看着方便,查找方便,清晰明了.但是xml完全可以使用注解代替,今天就扒一扒springboot中事务使用注解的玩法. springboot的事务也主要分为两大类,一是xml声明式事务,二是注解事务,注解事务也可以实现类似声明式事务的方法,关于注解声明式事务,目前网上搜索不到合适的资料,所以在这里

  • Spring实战之使用注解实现声明式事务操作示例

    本文实例讲述了Spring实战之使用注解实现声明式事务操作.分享给大家供大家参考,具体如下: 一 配置文件 <?xml version="1.0" encoding="GBK"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xm

  • spring boot基于注解的声明式事务配置详解

    事务配置 1.配置方式一 1)开启spring事务管理,在spring boot启动类添加注解@EnableTransactionManagement(proxyTargetClass = true):等同于xml配置方式的 <tx:annotation-driven />(注意:1项目中只需配置一次,2需要配置proxyTargetClass = true) 2)在项目中需要添加事务的类或方法上添加注解@Transactional(建议添加在方法上),一般使用默认属性即可,若要使用事务各属性

  • Spring注解 TX声明式事务实现过程解析

    环境搭建导入 maven依赖 <!--spring提供的数据库操作工具--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.2.RELEASE</version> </dependency> <!--c3p0 数据库连接池--> &

  • spring是如何实现声明式事务的

    前言 今天我们来讲讲spring的声明式事务. 开始 说到声明式事务,我们现在回顾一下事务这个概念,什么是事务呢,事务指的是逻辑上的⼀组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功.从而确保了数据的准确与安全.事务有着四大特性(ACID),分别是 原子性(Atomicity)原⼦性是指事务是⼀个不可分割的⼯作单位,事务中的操作要么都发⽣,要么都不发⽣. ⼀致性(Consistency)事务必须使数据库从⼀个⼀致性状态变换到另外⼀个⼀致性状态. 隔离性(Isolation)事务的隔离

  • SpringBoot声明式事务的简单运用说明

    关于事物的基本概念等这里就不介绍了. Spring声明式事物的实现,有两种方式:第一种是配置xml,第二种是使用相关注解(这两种方式可详见<程序员成长笔记(一)>的相关章节).SpringBoot中默认配置了第二种方式,所以,SpringBoot直接使用注解即可.下面介绍SpringBoot通过注解开启事物的使用. SpringBoot使用事物的步骤: 第一步:在启动类上开启事物支持 提示: @EnableTransactionManagement注解其实在大多数情况下,不是必须的,因为Spr

  • springboot开启声明式事务的方法

    springboot开启事务很简单,只需要一个注解@Transactional 就可以了.因为在springboot中已经默认对jpa.jdbc.mybatis开启了事事务,引入它们依赖的时候,事物就默认开启.当然,如果你需要用其他的orm,比如beatlsql,就需要自己配置相关的事物管理器. 准备阶段 以上一篇文章的代码为例子,即springboot整合mybatis,上一篇文章是基于注解来实现mybatis的数据访问层,这篇文章基于xml的来实现,并开启声明式事务. 环境依赖 在pom文件

  • Spring实战之使用XML方式管理声明式事务操作示例

    本文实例讲述了Spring实战之使用XML方式管理声明式事务操作.分享给大家供大家参考,具体如下: 一 配置文件 <?xml version="1.0" encoding="GBK"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"

  • Spring声明式事务注解之@EnableTransactionManagement解析

    Spring声明式事务注解之@EnableTransactionManagement 1. 说明 @EnableTransactionManagement声明在主配置类上,表示开启声明式事务,其原理是通过@Import导入TransactionManagementConfigurationSelector组件,然后又通过TransactionManagementConfigurationSelector导入组件AutoProxyRegistrar和ProxyTransactionManageme

  • Spring深入刨析声明式事务注解的源码

    目录 1.@EnableTransactionManagement 2.加载事务控制组件 2.1.AutoProxyRegistrar 2.2.ProxyTransactionManagementConfiguration 组件 2.3.上述组件如何关联起来的 2.4.invokeWithinTransaction⽅法 声明式事务很方便,尤其纯注解模式,仅仅几个注解就能控制事务了 思考:这些注解都做了什么?好神奇! @EnableTransactionManagement @Transactio

随机推荐