自定义事务
2016-05-19 16:07
309 查看
Spring的开启事务管理主要是通过@EnableTransactionManagement注解来实现的。 查看源码就会发现,这个注解主要是注入了两个类InfrastructureAdvisorAutoProxyCreator和BeanFactoryTransactionAttributeSourceAdvisor,而且这两个类是通过其他的Configure类导入的。
InfrastructureAdvisorAutoProxyCreator继承自AbstractAutoProxyCreator,自定义Aop里介绍过这个类,主要是读取Advisor类,并对符合的bean进行二次代理。
BeanFactoryTransactionAttributeSourceAdvisor就是被扫描的Advisor类。这个类会扫面被Transactional注释的类的方法,并提供TransactionInterceptor,来代理被注释的方法。
完整的代码参考Github,这里介绍一下几个关键的类。
自定义的注解,简便起见注解的属性就不列出来了,跟Transactional的属性一样。
DataSource和dao层,简便起见,用的内存式数据库h2,dao层用的是mybatis。
定义dao方法。
注入transactionManager。
InfrastructureAdvisorAutoProxyCreator是直接使用Spring内置的类。
BeanFactoryTransactionAttributeSourceAdvisor需要扫描自定义的注解,并嵌入到方法执行的前后,就需要自己定义了。 其中MySpringTransactionAnnotationParser继承自Spring内置的SpringTransactionAnnotationParser类,重写了扫描注解的方法。 MyTransactionInterceptor则继承了Spring内置的TransactionInterceptor重写了invoke方法,在事务方法开始的前后输出了部分信息。MyProxyTransactionManagementConfiguration则是参考的Spring的注入方式,组装BeanFactoryTransactionAttributeSourceAdvisor并注入相关的Bean。
观察程序的日志就会发现在Spring加载了被MyTransactional的方法,并放到了事务中执行。同时在方法执行前后输出了方法的一些信息。
Spring的事务管理是建立在Aop之上的,借用了Advisor和Interceptor的很多方法。扩展一下,还可以通过自定义注解,对相应的方法进行代理
InfrastructureAdvisorAutoProxyCreator继承自AbstractAutoProxyCreator,自定义Aop里介绍过这个类,主要是读取Advisor类,并对符合的bean进行二次代理。
BeanFactoryTransactionAttributeSourceAdvisor就是被扫描的Advisor类。这个类会扫面被Transactional注释的类的方法,并提供TransactionInterceptor,来代理被注释的方法。
完整的代码参考Github,这里介绍一下几个关键的类。
自定义的注解,简便起见注解的属性就不列出来了,跟Transactional的属性一样。
@Target({ ElementType.METHOD, ElementType.TYPE }) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface MyTransactional { .... }
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(); }
定义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(); }
注入transactionManager。
@Bean(name = "transactionManager") public PlatformTransactionManager transactionManager() { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); transactionManager.setDataSource(dataSource()); return transactionManager; }
InfrastructureAdvisorAutoProxyCreator是直接使用Spring内置的类。
@Bean @Order(Ordered.HIGHEST_PRECEDENCE) public InfrastructureAdvisorAutoProxyCreator advisorAutoProxyCreator() { return new InfrastructureAdvisorAutoProxyCreator(); }
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的方法,并放到了事务中执行。同时在方法执行前后输出了方法的一些信息。
结语
Spring的事务管理是建立在Aop之上的,借用了Advisor和Interceptor的很多方法。扩展一下,还可以通过自定义注解,对相应的方法进行代理
相关文章推荐
- Android 多线程及线程通信
- FTP使用 ---python
- 惹怒程序员的十件事!需求变更居然不被排第一!
- nginx 下 bootstrap fa 字体异常问题
- LeetCode 274 H-Index
- POJ 2349 Arctic Network (最小生成树)
- post 请求 application/x-www-form-urlencoded。android 中文 乱码
- ff文字省略号
- 透视校正插值(Perspective-Correct Interpolation)
- Win7系统启动失败出现错误提示0XC000000F的解决方法
- 常用sql语句记录--sqlserver
- Python脚本报错AttributeError: ‘module’ object has no attribute’xxx’解决方法
- 软件质量
- openstack-ansible Chapter 4. Deployment configuration
- mac 终端下的命令大全
- 超图对接NSDTF-DEM数据
- python3 使用 protobuf3 序列化踩过的坑
- libxml/tree.h file not found解决办法
- Windows 7下安装使用Sublime Text 3
- Jmeter CSV 参数化/检查点/断言