转自:

http://www.jianshu.com/p/5347a462b3a5

前言

上一篇文章讲了Spring的Aop,这里讲一下Spring的事务管理,Spring的事务管理是建立在Aop的基础上的,相比Aop,事务管理的实现耦合性比较小,自定义就比较简单了。

自定义事务

Spring的开启事务管理主要是通过@EnableTransactionManagement注解来实现的。
查看源码就会发现,这个注解主要是注入了两个类InfrastructureAdvisorAutoProxyCreatorBeanFactoryTransactionAttributeSourceAdvisor,而且这两个类是通过其他的Configure类导入的。

  • InfrastructureAdvisorAutoProxyCreator继承自AbstractAutoProxyCreator自定义Aop里介绍过这个类,主要是读取Advisor类,并对符合的bean进行二次代理。
  • BeanFactoryTransactionAttributeSourceAdvisor就是被扫描的Advisor类。这个类会扫面被Transactional注释的类的方法,并提供TransactionInterceptor,来代理被注释的方法。

完整的代码参考Github,这里介绍一下几个关键的类。

  1. 自定义的注解,简便起见注解的属性就不列出来了,跟Transactional的属性一样。

    @Target({ ElementType.METHOD, ElementType.TYPE })
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface MyTransactional {
    ....
    }
  2. DataSource和dao层,简便起见,用的内存式数据库h2,dao层用的是mybatis。

     @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean() {
    SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
    sqlSessionFactoryBean.setDataSource(dataSource());
    return sqlSessionFactoryBean;
    } @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
    MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
    mapperScannerConfigurer.setBasePackage("org.wcong.test.spring.mybatis.mapper");
    return mapperScannerConfigurer;
    } @Bean
    public DataSource dataSource() {
    EmbeddedDatabaseBuilder embeddedDatabaseBuilder = new EmbeddedDatabaseBuilder();
    return embeddedDatabaseBuilder.setType(EmbeddedDatabaseType.H2).build();
    }
  3. 定义dao方法。
    public interface DbTest {
    @Select("select count(*) from db_test")
    int count();
    @Insert("insert into db_test(id,date,content) values(#{id},now(),#{content})")
    @MyTransactional
    int add(TestModel testModel);
    @Insert("create table db_test(id int,date time,content varchar)")
    int createTable();
    }
  4. 注入transactionManager。
     @Bean(name = "transactionManager")
    public PlatformTransactionManager transactionManager() {
    DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
    transactionManager.setDataSource(dataSource());
    return transactionManager;
    }
  5. InfrastructureAdvisorAutoProxyCreator是直接使用Spring内置的类。
     @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public InfrastructureAdvisorAutoProxyCreator advisorAutoProxyCreator() {
    return new InfrastructureAdvisorAutoProxyCreator();
    }
  6. BeanFactoryTransactionAttributeSourceAdvisor需要扫描自定义的注解,并嵌入到方法执行的前后,就需要自己定义了。
    其中MySpringTransactionAnnotationParser继承自Spring内置的SpringTransactionAnnotationParser类,重写了扫描注解的方法。
    MyTransactionInterceptor则继承了Spring内置的TransactionInterceptor重写了invoke方法,在事务方法开始的前后输出了部分信息。
    MyProxyTransactionManagementConfiguration则是参考的Spring的注入方式,组装BeanFactoryTransactionAttributeSourceAdvisor并注入相关的Bean。
     public static class MySpringTransactionAnnotationParser extends SpringTransactionAnnotationParser {
    @Override
    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {
    AnnotationAttributes attributes = AnnotatedElementUtils
    .getMergedAnnotationAttributes(ae, MyTransactional.class);
    if (attributes != null) {
    return parseTransactionAnnotation(attributes);
    } else {
    return null;
    }
    }
    public TransactionAttribute parseTransactionAnnotation(MyTransactional ann) {
    return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
    }
    }
    public static class MyTransactionInterceptor extends TransactionInterceptor {
    @Override
    public Object invoke(final MethodInvocation invocation) throws Throwable {
    System.out.println("transaction method :" +
    invocation.getMethod().getDeclaringClass().getName() + "." + invocation.getMethod().getName());
    Object object = super.invoke(invocation);
    System.out.println(invocation.getMethod().getName() + " result :" + object);
    return object;
    }
    }
    @Configuration
    public static class MyProxyTransactionManagementConfiguration {
    protected PlatformTransactionManager txManager;
    @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
    BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
    advisor.setTransactionAttributeSource(transactionAttributeSource());
    advisor.setAdvice(transactionInterceptor());
    advisor.setOrder(Ordered.LOWEST_PRECEDENCE);
    return advisor;
    }
    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionAttributeSource transactionAttributeSource() {
    return new AnnotationTransactionAttributeSource(new MySpringTransactionAnnotationParser());
    }
    @Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionalEventListenerFactory transactionalEventListenerFactory() {
    return new TransactionalEventListenerFactory();
    }
    @Autowired(required = false)
    void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
    if (CollectionUtils.isEmpty(configurers)) {
    return;
    }
    if (configurers.size() > 1) {
    throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
    }
    TransactionManagementConfigurer configurer = configurers.iterator().next();
    this.txManager = configurer.annotationDrivenTransactionManager();
    }
    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionInterceptor transactionInterceptor() {
    TransactionInterceptor interceptor = new MyTransactionInterceptor();
    interceptor.setTransactionAttributeSource(transactionAttributeSource());
    if (this.txManager != null) {
    interceptor.setTransactionManager(this.txManager);
    }
    return interceptor;
    }
    }

观察程序的日志就会发现在Spring加载了被MyTransactional的方法,并放到了事务中执行。同时在方法执行前后输出了方法的一些信息。

customizeTransactional.jpg

结语

Spring的事务管理是建立在Aop之上的,借用了AdvisorInterceptor的很多方法。扩展一下,还可以通过自定义注解,对相应的方法进行代理。

文/wcong(简书作者)
原文链接:http://www.jianshu.com/p/5347a462b3a5
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

深入Spring:自定义事务管理的更多相关文章

  1. Spring之事务管理

        事务管理对于企业应用至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.     就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到 ...

  2. Spring学习笔记五:Spring进行事务管理

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6776256.html  事务管理主要负责对持久化方法进行统一的提交或回滚,Spring进行事务管理即我们无需在 ...

  3. Spring的事务管理

    事务 事务:是逻辑上一组操作,要么全都成功,要么全都失败. 事务特性(ACID) 原子性:事务不可分割 一致性:事务执行的前后,数据完整性保持一致 隔离性:一个事务执行的时候,不应该受到其他事务的打扰 ...

  4. spring笔记--事务管理之声明式事务

    事务简介: 事务管理是企业级应用开发中必不可少的技术,主要用来确保数据的完整性和一致性, 事务:就是一系列动作,它们被当作一个独立的工作单元,这些动作要么全部完成,要么全部不起作用. Spring中使 ...

  5. Spring应用——事务管理

    事务基础:请参看:http://www.cnblogs.com/solverpeng/p/5720306.html 一.Spring 事务管理 1.前提:事务管理器 在使用 Spring 声明式事务管 ...

  6. spring+mybatis事务管理

    spring+mybatis事务管理 最近在和朋友做一个项目,考虑用springmvc+mybatis来做,之前在公司工作吧,对于数据库这块的配置也有人再弄,最近因为这个项目,我就上网学习了一些关于数 ...

  7. spring,mybatis事务管理配置与@Transactional注解使用[转]

    spring,mybatis事务管理配置与@Transactional注解使用[转] spring,mybatis事务管理配置与@Transactional注解使用 概述事务管理对于企业应用来说是至关 ...

  8. Spring高级事务管理难点剖析

    1Spring事务传播行为 所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播.Spring支持7种事务传播行为 PROPAGATION_REQUIRED(加入已有事务) 如果当前没 ...

  9. CSDN上看到的一篇有关Spring JDBC事务管理的文章(内容比较全) (转)

    JDBC事务管理 Spring提供编程式的事务管理(Programmatic transaction manage- ment)与声明式的事务管理(Declarative transaction ma ...

随机推荐

  1. POJ2536 Gopher II(二分图最大匹配)

    Gopher II Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9005   Accepted: 3724 Descrip ...

  2. Python自动化开发 - Django基础

    本节内容 一.什么是web框架 二.MVC和MTV视图 三.Django基本命令 四.路由配置系统 五.编写视图 六.Template 七.ORM 一.什么是web框架 对于所有的web应用,本质上其 ...

  3. JAVA的初始化顺序

    这里主要是介绍JAVA的类的初始化顺序,比较基础:主要是以例子演示为主: 例子一: 1 package com.cnblog.GDUTtiantian; 2 3 /** 4 * 5 * @author ...

  4. 分形之谢尔宾斯基(Sierpinski)四面体

    前面讲了谢尔宾斯基三角形,这一节的将对二维三角形扩展到三维,变成四面体.即将一个正四面体不停地拆分,每个正四面体可以拆分成四个小号的正四面体.由二维转变到三维实现起来麻烦了许多.三维的谢尔宾斯基四面体 ...

  5. [LintCode] Longest Increasing Continuous subsequence

    http://www.lintcode.com/en/problem/longest-increasing-continuous-subsequence/# Give you an integer a ...

  6. [转载]持续交付和DevOps的前世今生

    作者/分享人:乔梁,20年IT老兵,腾讯公司高级管理顾问,敏捷和精益开发专家,持续交付领域先行者.曾就职于百度,国内多个知名互联网公司的企业教练. 历年QCon技术大会的讲师和专题出品人. 这是一个新 ...

  7. 【BZOJ2001】 [Hnoi2010]City 城市建设

    BZOJ2001 [Hnoi2010]City 城市建设 Solution 我们考虑一下这个东西怎么求解? 思考无果...... 咦? 好像可以离线cdq,每一次判断一下如果这条边如果不选就直接删除, ...

  8. 如何给wp(Windows phone)中搜索关键字加亮?

    问题来源 最近在群里看到群友讨论在wp中有个搜索功能,要求搜索关键字在搜索结果内容中加亮(即加颜色),由于wp中没有自带这样的控件,于是大家各抒自见,有人说用第三方控件,有人说用richtextbox ...

  9. [POC]K8 DLLhijack Test

    POC: 2016.11 Winrar却持 XP资源管理器却持 DLL却持VS全版本 https://www.cnblogs.com/k8gege/p/10261254.html POC:https: ...

  10. Ubuntu 12.04 安装Redis并设置主从复制

    今天想在Ubuntu上安装一个Redis服务器并配置Master-Slave,一开始懒得连VPN就查了一些国内的文章,不知道是没有亲自验证过的转载文章,还是版本问题造成的,发现按照步骤都没能成功完成配 ...