深入Spring:自定义事务管理

作者: wcong | 来源:发表于2016-04-27 17:46 被阅读7793次

前言

上一篇文章讲了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 {
    ....
}
  1. 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();
    }
  1. 定义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();
}
  1. 注入transactionManager。
    @Bean(name = "transactionManager")
    public PlatformTransactionManager transactionManager() {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource());
        return transactionManager;
    }
  1. InfrastructureAdvisorAutoProxyCreator是直接使用Spring内置的类。
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public InfrastructureAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        return new InfrastructureAdvisorAutoProxyCreator();
    }
  1. 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的很多方法。扩展一下,还可以通过自定义注解,对相应的方法进行代理。

相关文章

网友评论

    本文标题:深入Spring:自定义事务管理

    本文链接:https://www.haomeiwen.com/subject/msmplttx.html