深入Spring:自定義事務管理


轉自:

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
著作權歸作者所有,轉載請聯系作者獲得授權,並標注“簡書作者”。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM