Spring事务控制
Spring提供了一种声明式事务控制。只要追加配置信息,就可以对事务进行控制,不用Java编码。
-
原有JDBC控制模式
public void someService(){ try{ //取消自动提交con.setAutoCommit(false); AccountDao.update(A,-1000);//账户减钱操作 AccountDao.update(B,1000);//账户加钱操作 //事务提交con.commit() }catch(){ //事务回滚con.rollback() } }
-
Spring控制模式
@Transactional public void someService(){ AccountDao.update(A,-1000);//账户减钱操作 AccountDao.update(B,1000);//账户加钱操作 }
xxx.开启事务 someService(); 有异常调用xxx.回滚事务/没有异常调用xxx.提交事务
DataSourceTransactionManager//JDBC、MyBatis
HibernateTransactionManager//Hibernate框架 -
Spring事务使用方法
-
在业务方法前追加@Transactional标记
@Transactional public void someService(){ AccountDao.update(A,-1000);//账户减钱操作 AccountDao.update(B,1000);//账户加钱操作 }
-
在Spring配置中追加事务管理配置
<!-- 定义事务控制的TransactionManager --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dbcpDS"></property> </bean> <!-- 开启@Transactional标记 --> <tx:annotation-driven transaction-manager="txManager"/>
-
-
@Transactional事务特性(了解)
-
readOnly
默认是false,支持读和写操作。如果只有查询可以使用readOnly=true;有增删改需要使用false.
-
rollbackFor
默认是RuntimeException,可以指定回滚异常类型。 @Transactional(rollbackFor=MyException.class)
意思:标记所在方法如果抛出了MyException也进行事务回滚。
-
isolation(事务隔离级别)
默认Isolation.DEFAULT,根据数据库类型定义。Oracle采用READCOMMITED。级别由低到高分为READUNCOMMITED、READCOMMITED、REPEATABLEREAD、SERIALIZABLE。
级别越低并发处理越强、但是安全性越差。实际采用默认级别,然后个别处理采用逻辑锁。
-
propagation(事务传播)
默认Propagation.REQUIRED,其他的还有REQUIRESNEW、NOTSUPPORTED等。实际采用默认类型。
@Transactional public void f1(){ //操作1 f2(); } @Transactional(propagation=Propagation.REQUIRED) public void f2(){ //操作2,失败会撤销f1中的操作1操作 }
-
Spring AOP
AOP简介
面向切面编程,Aspect Oriented Programming
面向对象编程,Object Oriented Programming
语法–》理解+设计(方法、属性)–》设计思想和设计模式
概念–》使用方法–》概念理解
面向切面编程:涉及切面、切入点、通知、目标等概念。 优点:可以在不修改原有目标组件代码逻辑情况下,追加扩展性功能、重用性、灵活性、扩展性。 目地:为了将一些传统的业务和共同业务进行隔离,然后通过配置方式结合在一起工作。
案例1:调用所有Controller方法之前打印一个消息
- 目标:所有Controller方法,(pointcut切入点)
- 切入时机:方法之前,(Advice通知)
- 追加功能:打印消息,(Aspect切面组件)
相关概念
-
切面(Aspect)追加什么功能?
指的是在共同位置和时机要切入的共同处理。切面组件包含了共同处理,可以通过AOP配置切入其他某一批组件方法上。
//前置通知方法 public void xxx(){...}; //最终通知方法 public void xxx(){...}; //环绕通知方法,连接点信息(可以获取目标方法名、参数、类型等信息) public Object xxx(ProceedingJoinPoint pjp) throws Throwable{...}; //异常通知方法,e是目标方法抛出的异常对象 public void xxx(Exception e){...}; //后置通知方法,obj是目标方法返回的结果信息 public void xxx(Object obj){...};
-
切入点(Pointcut)给谁追加功能?
指的是目标组件及其方法,该方法要追加切面组件处理。Spring提供了以下切入点表达式,用于指定目标。
- 方法限定表达式
execution(修饰符? 返回类型 方法名(参数) throws 异常类型?)
//匹配以load开始方法 execution(* load*(..)) //匹配EvaluationService组件所有方法 execution(* cn.xdl.service.EvaluationService.*(..)) //匹配cn.xdl.service包下所有组件所有方法 execution(* cn.xdl.service.*.*(..)) //匹配cn.xdl.service包及子包下所有组件所有方法 execution(* cn.xdl.service..*.*(..))
- 类型限定表达式
within(类型)
//匹配EvaluationService组件所有方法 within(cn.xdl.service.EvaluationService) //匹配cn.xdl.service包下所有组件所有方法 within(cn.xdl.service.*) //匹配cn.xdl.service包及子包下所有组件所有方法 within(cn.xdl.service..*)
- bean名称限定表达式
bean(Sring容器中bean对象的id名)
//匹配id=evaluationController的bean对象所有方法 bean(evaluationController) //匹配所有id名以Controller结尾的bean对象所有方法 bean(*Controller)
-
通知(Advice) 什么时候加功能?
指的是切面组件切入目标方法的时机或位置。Spring提供了多种通知类型,使用不同通知可以在不同位置切入。
try{ //环绕通知-前置部分 //前置通知–>aop:before 原有组件方法 //后置通知–>aop:after-returning //环绕通知-后置部分 }catch(){ //异常通知–>aop:after-throwing }finally{ //最终通知–>aop:after }
AOP注解配置方法
-
开启组件扫描,将功能组件扫描到Spring容器
-
开启AOP注解配置,aop:aspectj-autoproxy/
@Aspect、@Before、@After、@Pointcut等标记
案例2:性能检测功能
需求:对请求处理进行检测,计算接收请求和响应之间的时间差。
-
切面(加什么功能?)
计时功能
-
切入点(给谁加?)
所有controller方法。
bean(*Controller)
within(cn.xdl.web.controller…*)
-
通知(什么时候加?)
controller方法前开始计时,controller方法结束后结束计时
使用环绕通知。@Around
案例3:异常处理
-
切面(加什么功能?)
将异常信息写入文件中。
-
切入点(给谁加?)
所有controller方法。
bean(*Controller)
-
通知(什么时候加?)
controller方法执行抛出异常时
使用异常通知。@AfterThrowing