Spring的事务管理和Aop
2018-01-17 18:13
246 查看
事务和aop也是面试和Spring代码开发中老生常谈的问题,对于这块,我自己的感觉是都能说出是干嘛的也能写出东西,但是详细的深入的了解,和他们之间的关系其实不是很清楚。每次有人问aop能干嘛时,一般就直接说哥,可以完成事务,或者拦截器等有关面向切面的功能,一般也就结了。但是,这是不好的,在这里想总结一下,事务管理和aop之间的联系,同时主要说下Spring事务管理的问题。
通俗理解,事务其实就是一系列指令的集合。
AOP:
即面向切面编程,利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事务。
可以想到,因为aop面向切面的特性,在某些dao或者service执行时,可以该方法之前和之后,加入事务管理有关代码其。来实现一个面向切面的事务管理。也就是aop可以帮助实现事务管理,但不是所有的事务管理都是AOP实现的。
其实对于事务管理主要分成两种声明类型,分别是
unchecked异常,
即RuntimeException(运行时异常),即不需要try...catch...或throws 机制去处理的异常才会回滚。 除了unchecked异常,其他继承自java.lang.Exception得异常统称为Checked Exception,是不会回滚的。比如说,SQLException, TimeoutException这类的异常。编译的时候也会要求你try-catch住。这种情况啊报错,srping默认为你会自己在catch中对异常进行处理,所以他就不会帮你回滚了。这个我觉得逻辑上也是说得通的。那我们想要对这些异常也回滚怎么办呢,很多种方式,我说几种:
1.注解情况下用@Transactional(rollbackFor = { Exception.class }) ,手动设置rollback错误类型
2.catch后 throw new RuntimeException 让事务回滚; 让cath抛出runtimeException异常
3.如果是用编程式在内部写代码的形式也可以在catch中手动调用rollback
public void testdelivery(){
//定义事务隔离级别,传播行为,
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
//事务状态类,通过PlatformTransactionManager的getTransaction方法根据事务定义获取;获取事务状态后,Spring根据传播行为来决定如何开启事务
TransactionStatus status = txManager.getTransaction(def);
jdbcTemplate = new JdbcTemplate(dataSource);
int i = jdbcTemplate.queryForInt(COUNT_SQL);
System.out.println("表中记录总数:"+i);
try {
jdbcTemplate.update(INSERT_SQL, "1");
txManager.commit(status); //提交status中绑定的事务
} catch (RuntimeException e) {
txManager.rollback(status); //回滚
}
i = jdbcTemplate.queryForInt(COUNT_SQL);
System.out.println("表中记录总数:"+i);
}
我感觉应该是很清楚了。有啥补充,我后期再加上吧!开心~
事务管理:
我们在实际业务场景中,经常会遇到数据频繁修改读取的问题。在同一时刻,不同的业务逻辑对同一个表数据进行修改,这种冲突很可能造成数据不可挽回的错乱,所以我们需要用事务来对数据进行管理。事务必须服从ACID原则。ACID指的是原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)。通俗理解,事务其实就是一系列指令的集合。
AOP:
即面向切面编程,利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事务。
可以想到,因为aop面向切面的特性,在某些dao或者service执行时,可以该方法之前和之后,加入事务管理有关代码其。来实现一个面向切面的事务管理。也就是aop可以帮助实现事务管理,但不是所有的事务管理都是AOP实现的。
其实对于事务管理主要分成两种声明类型,分别是
编程式事务:所谓编程式事务指的是通过编码方式实现事务,即类似于JDBC编程实现事务管理。管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。
声明式事务:管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。 关于编程式事务和声明式事务的代码案例,这篇博文我是赞同的。http://blog.csdn.net/liaohaojian/article/details/70139151。反而很多高票的其他博客讲解代码是对的,但是意义是错的,这两种事务的区别主要是如我说的意义区分,而不是用了注解就怎么怎么样了。 咱们继续讲讲事务,事务的还有个问题就是,新手很容易犯的一个错误就是,以为只要引用了事务就万事大吉了,其实是不太了解原理,这里面还有一层问题就是,事务的调起机制。 事务的回滚与不回滚 先上结论,事务在不配置的情况下默认只有:unchecked异常,
即RuntimeException(运行时异常),即不需要try...catch...或throws 机制去处理的异常才会回滚。 除了unchecked异常,其他继承自java.lang.Exception得异常统称为Checked Exception,是不会回滚的。比如说,SQLException, TimeoutException这类的异常。编译的时候也会要求你try-catch住。这种情况啊报错,srping默认为你会自己在catch中对异常进行处理,所以他就不会帮你回滚了。这个我觉得逻辑上也是说得通的。那我们想要对这些异常也回滚怎么办呢,很多种方式,我说几种:
1.注解情况下用@Transactional(rollbackFor = { Exception.class }) ,手动设置rollback错误类型
2.catch后 throw new RuntimeException 让事务回滚; 让cath抛出runtimeException异常
3.如果是用编程式在内部写代码的形式也可以在catch中手动调用rollback
public void testdelivery(){
//定义事务隔离级别,传播行为,
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
//事务状态类,通过PlatformTransactionManager的getTransaction方法根据事务定义获取;获取事务状态后,Spring根据传播行为来决定如何开启事务
TransactionStatus status = txManager.getTransaction(def);
jdbcTemplate = new JdbcTemplate(dataSource);
int i = jdbcTemplate.queryForInt(COUNT_SQL);
System.out.println("表中记录总数:"+i);
try {
jdbcTemplate.update(INSERT_SQL, "1");
txManager.commit(status); //提交status中绑定的事务
} catch (RuntimeException e) {
txManager.rollback(status); //回滚
}
i = jdbcTemplate.queryForInt(COUNT_SQL);
System.out.println("表中记录总数:"+i);
}
我感觉应该是很清楚了。有啥补充,我后期再加上吧!开心~
相关文章推荐
- 数据库事务的四大特性、隔离级别以及Spring中如何利用AOP进行事务管理
- Spring的AOP和事务管理机制概览
- Spring4笔记9--Spring的事务管理(AOP应用的例子)
- spring+aop管理事务
- SpringMVC + Spring + MyBatis 学习笔记:SpringMVC和Spring一同工作的时候,AOP事务管理不起作用的解决方法
- spring采用aop配置事务管理的样例
- spring 之AOP的典型应用就是事务管理
- 对spring中AOP的理解(事务管理)
- Spring事务管理—aop:pointcut expression解析
- 纯JDBC、Hibernate、Spring的AOP声明式事务管理小结
- Spring基于AOP的事务管理
- Spring事务管理—aop:pointcut expression解析
- spring aop 注解 事务管理 以及各种参数分析
- spring 之AOP的典型应用就是事务管理
- 两种Spring事务管理方式:编程式、声明式 跟spring aop管理事务有什么不同?
- Spring的AOP和事务管理机制概览
- spring框架学习(六)AOP事务及spring管理事务方式之Template模板
- 27Spring_的事务管理_银行转账业务加上事务控制_基于tx.aop进行声明式事务管理
- spring中的aop的应用之声明事务管理
- 懒得笔记5 spring aop 整合hibernate 事务管理