深入Spring:自定义事务管理
转自:
http://www.jianshu.com/p/5347a462b3a5
前言
上一篇文章讲了Spring的Aop,这里讲一下Spring的事务管理,Spring的事务管理是建立在Aop的基础上的,相比Aop,事务管理的实现耦合性比较小,自定义就比较简单了。
自定义事务
Spring的开启事务管理主要是通过@EnableTransactionManagement注解来实现的。
查看源码就会发现,这个注解主要是注入了两个类InfrastructureAdvisorAutoProxyCreator和BeanFactoryTransactionAttributeSourceAdvisor,而且这两个类是通过其他的Configure类导入的。
- 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的很多方法。扩展一下,还可以通过自定义注解,对相应的方法进行代理。
原文链接:http://www.jianshu.com/p/5347a462b3a5
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
深入Spring:自定义事务管理的更多相关文章
- Spring之事务管理
事务管理对于企业应用至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性. 就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到 ...
- Spring学习笔记五:Spring进行事务管理
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6776256.html 事务管理主要负责对持久化方法进行统一的提交或回滚,Spring进行事务管理即我们无需在 ...
- Spring的事务管理
事务 事务:是逻辑上一组操作,要么全都成功,要么全都失败. 事务特性(ACID) 原子性:事务不可分割 一致性:事务执行的前后,数据完整性保持一致 隔离性:一个事务执行的时候,不应该受到其他事务的打扰 ...
- spring笔记--事务管理之声明式事务
事务简介: 事务管理是企业级应用开发中必不可少的技术,主要用来确保数据的完整性和一致性, 事务:就是一系列动作,它们被当作一个独立的工作单元,这些动作要么全部完成,要么全部不起作用. Spring中使 ...
- Spring应用——事务管理
事务基础:请参看:http://www.cnblogs.com/solverpeng/p/5720306.html 一.Spring 事务管理 1.前提:事务管理器 在使用 Spring 声明式事务管 ...
- spring+mybatis事务管理
spring+mybatis事务管理 最近在和朋友做一个项目,考虑用springmvc+mybatis来做,之前在公司工作吧,对于数据库这块的配置也有人再弄,最近因为这个项目,我就上网学习了一些关于数 ...
- spring,mybatis事务管理配置与@Transactional注解使用[转]
spring,mybatis事务管理配置与@Transactional注解使用[转] spring,mybatis事务管理配置与@Transactional注解使用 概述事务管理对于企业应用来说是至关 ...
- Spring高级事务管理难点剖析
1Spring事务传播行为 所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播.Spring支持7种事务传播行为 PROPAGATION_REQUIRED(加入已有事务) 如果当前没 ...
- CSDN上看到的一篇有关Spring JDBC事务管理的文章(内容比较全) (转)
JDBC事务管理 Spring提供编程式的事务管理(Programmatic transaction manage- ment)与声明式的事务管理(Declarative transaction ma ...
随机推荐
- ZUFE2481 神奇的字符串 2017-05-12 16:41 39人阅读 评论(0) 收藏
2481: 神奇的字符串 时间限制: 3 Sec 内存限制: 256 MB 提交: 8 解决: 3 [提交][状态][讨论版] 题目描述 输入 输出 样例输入 abcb 1000 1100 350 ...
- 如何防止ElasticSearch集群出现脑裂现象
什么是“脑裂”现象? 由于某些节点的失效,部分节点的网络连接会断开,并形成一个与原集群一样名字的集群,这种情况称为集群脑裂(split-brain)现象.这个问题非常危险,因为两个新形成的集群会同时索 ...
- Effective C++ 第二版 31)局部对象引用和函数内new的指针 32)推迟变量定义
条款31 千万不要返回局部对象的引用, 不要返回函数内部用new初始化的指针的引用 第一种情况: 返回局部对象的引用; 局部对象--仅仅是局部的, 在定义时创建, 在离开生命空间时被销毁; 所谓生命空 ...
- (25)uniGUI for C++ builder之UniHTMLMemo初使用及uniGUI如何调用javaScript
(25)uniGUI for C++ builder之UniHTMLMemo初使用及uniGUI如何调用javaScript 2018年09月29日 22:58:20 中国银行之路在脚下 阅读数:11 ...
- spring mvc 的请求流程
SpringMVC核心处理流程: 1.DispatcherServlet前端控制器接收发过来的请求,交给HandlerMapping处理器映射器 2.HandlerMapping处理器映射器,根据请求 ...
- java异步线程
使用一个ExecutorService,增加两个不可取消的子线程任务,并且获取他们的返回值. @org.junit.Test public void testFuture() throws Int ...
- MVC所有的ActionResult
一.所有的Controller都继承自System.Web.Mvc.Controller 目前ASP.NET MVC3默认提供了多种ActionResult的实现,在System.Web.Mvc命名空 ...
- MVC 5使用ViewData(模型)显示数据
看过此篇<MVC 5使用ViewData(对象)显示数据>http://www.cnblogs.com/insus/p/3377178.html 都明白在控制器使用ViewData(obj ...
- google breakpad for linux(2)
breakpad 是什么 breakpad 是一个包含了一系列库文件和工具的开源工具包,使用它可以帮助我们在程序崩溃后进行一系列的后续处理,如现场的保存(core dump),及事后分析(重建 cal ...
- 关于IE9 table显示错位的问题
首先,win10无法安装IE9,所以需要用IE11模拟IE9,这样:http://www.w10zj.com/Win10xy/Win10yh_638.html: 其次,table显示错位的可能原因:h ...