自定义事务

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的很多方法。扩展一下,还可以通过自定义注解,对相应的方法进行代理

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值