1、 未来蓝图软件教育 http:/www.itfuture.org第 1 页 共 9 页Spring 拦截器中的事务管理阶段目标:1、掌握什么是 spring 的数据库操作和事务管理2、spring 数据库操作的实现步骤3、spring 对数据库操作的事务管理4、spring 的事务管理与 Aop 的关系4、总结 spring 事务管理的几种实现方式、区别及优劣5、熟练在 ssh 项目中使用 spring 的数据操作和事务管理本章课时:3 课时一、关于 Spring 拦截器中的数据库操作和事务管理Spring 中的事务管理是通过 AOP 代理来实现的,对被代理对象的每个方法进行拦截,在方法执行前
2、启动事务,方法执行完后根据是否有异常和异常的种类进行提交或回滚。 如果要在方法执行前或后或抛出异常后加上一个自己的拦截器,或者一个环绕拦截器,在拦截器中执行一些操作,比如执行一些数据库操作,记录一些信息,这些操作通过调用一个服务类的方法来执行,这个方法也在 spring 事务管理拦截器的管理之下,那么这个记录方法需要在另一个事务中进行,而不是与被拦截方法在同一个事务中,不然如果被拦截方法抛出异常需要回滚时,所作的记录也会被回滚,当然有时候确实需要同时回滚,那就要放在同一个事务中。 这和自己的拦截器和事务管理的拦截器的执行顺序有一定关系,spring 事务管理拦截器是一个环绕通知,在被拦截方法执
3、行前启动事务,执行后完成事务,如果自己的拦截器被 spring 事务管理拦截器包围在里面,那么在自己的拦截器运行时,spring 已经启动了一个事务,如果你的记录信息方法需要与被拦截方法同在一个事务中,将你的记录信息方法的事务传播属性设为默认的REQUIRED 就可以了。如果你记录信息的方法需要单独的一个事务环境,那就要把事务传播属性设为 REQUIRES_NEW了,这样 spring 事务管理器会新建一个事务,并且新建一个 session 连接,因为一个数据库连接不可能同时有两个事务,记录信息完了提交事务并且把新建的 session 连接关闭,自己的拦截器退出后继续执行被拦截的方法或它的事务
4、处理。 相反如果自己的拦截器在 spring 事务管理拦截器的外面,那么记录信息的方法会在一个单独的事务中执行,并提交,不管它的事务传播属性是 REQUIRES_NEW 还是 REQUIRED,因为与被拦截方法的事务处理没有交叉,并且可以使用同一个 session 连接如果是 OpenSessionInViewFilter。 未来蓝图软件教育 http:/www.itfuture.org第 2 页 共 9 页所以如果记录信息和被拦截方法要在不同事务中执行,分别提交,那么最好将自己的拦截器设在 spring 事务管理器拦截器的外面;如果需要将记录信息和被拦截方法在同一个事务中处理,必须将自己的拦
5、截器被包围在 spring 事务管理拦截器中,并且记录信息方法的事务传播属性为默认的 REQUIRED。 设置拦截器的执行顺序可以让拦截器处理类实现 org.springframework.core.Ordered 接口,在 spring 配置文件的 AOP 设置中设定自己的拦截器和 spring 事务管理拦截器的执行顺序,将自己的拦截的序号排在 spring 事务管理的前面,就可以将该拦截器放到事务管理拦截器的外面执行了,对于 before 通知方式会先于事务管理拦截器执行,对于 after returning 和 after 和 after throwing 通知方式会后于事务管理拦截器的
6、执行,对于 around 通知方式会包围事务管理拦截器执行。 二、Spring 事务管理Spring 提供的事务管理可以分为两类:编程式的和声明式的。编程式的,比较灵活,但是代码量大,存在重复的代码比较多;声明式的比编程式的更灵活。(一) 、声明式事务管理通常建议采用声明式事务管理。声明式事务管理的优势非常明显:代码中无需关于关注事务逻辑,让 Spring 声明式事务管理负责事务逻辑,声明式事务管理无需与具体的事务逻辑耦合,可以方便地在不同事务逻辑之间切换。声明式事务管理的配置方式,通常有如下三种:1、使用 TransactionProxyFactoryBean 创建事务代理(通常事务代理以
7、Service 层为目标 bean)(1)、第一种使用方式:使用 TransactionProxyFactoryBean 为目标 bean 生成事务代理的配置。此方式是最传统,配置文件最臃肿、难以阅读的方式。/配置 hibernate 的事务管理器,使用 springz 中的 HibernateTransactionManager 类,该类实现了PlatformTransactionManager 接口,针对 hibernate 持久化连接的特定实现/Dao/使用 TransactionProxyFactoryBean 创建事务代理( 通常事务代理以 Service 层为目标 bean)/配置
8、 xtyhbService bean 的事务代理未来蓝图软件教育 http:/www.itfuture.org第 3 页 共 9 页PROPAGATION_REQUIREDPROPAGATION_REQUIREDPROPAGATION_REQUIREDPROPAGATION_REQUIRED,readOnly(2)、第二种使用方式: 使用 TransactionProxyFactoryBean 为目标 bean 生成事务代理的配置,采用 bean 配置继承的事务代理配置方式,比较简洁,但依然是增量式配置。/配置 hibernate 的事务管理器,使用 HibernateTransactionM
9、anager 类,该类实现了PlatformTransactionManager 接口,针对 hibernate 持久化连接的特定实现/需要生成代理的目标 bean/配置抽象的基础代理PROPAGATION_REQUIREDPROPAGATION_REQUIREDPROPAGATION_REQUIREDPROPAGATION_REQUIRED,readOnly/通过 bean配置的继承来声明xtyhbService bean的事务代理未来蓝图软件教育 http:/www.itfuture.org第 4 页 共 9 页2.使用自动创建代理简化事务配置使用 BeanNameAutoProxyCre
10、ator,根据 bean name 自动生成事务代理的方式,这是直接利用Spring 的 AOP 框架配置事务代理的方式,需要对 Spring 的 AOP 框架有所理解。但这种方式避免了增量式配置,效果非常不错。使用 BeanNameAutoProxyCreator 和DefaultAdvisorAutoProxyCreator 创建代理时,并不一定是创建事务代理,关键在于传入的拦截器,如果传入事务拦截器,将可自动生成事务代理。如果传入日志拦截器,将可自动生成日志代理。/配置事务拦截器bean/事务拦截器需要注入一个事务管理器/定义事务传播属性PROPAGATION_REQUIREDPROPA
11、GATION_REQUIREDPROPAGATION_REQUIREDPROPAGATION_REQUIREDPROPAGATION_REQUIRED,readOnly/给在列表中定义的需要代理的Bean的创建代理器BeanNameAutoProxyCreator(Auto proxy creator that identifies beans to proxy via a list of names)xtyhbServicei/此处可以增加其他需要创建事务代理的beantransactionInterceptor/此处可以增加其他新的 Interceptor/配置事务代理目标 bean xt
12、yhbServicei,该目标 bean 在生成对象后,自动生成代理未来蓝图软件教育 http:/www.itfuture.org第 5 页 共 9 页3. Spring 封装 AspectJ 的方式来声明事务配置/事务管理器未来蓝图软件教育 http:/www.itfuture.org第 6 页 共 9 页三、Spring 事务管理应用案例1、Spring 封装 AspectJ 的方式来声明事务的应用案例下面以一个常用的异常拦截器的例子来说明事务应用:一个用户登录的功能,Spring 对service 中的每个方法进行事务管理,在检测用户是否存在的 service 方法上同时加一个异常拦截器
13、,当用户不存在或密码不正确时该方法会抛出异常,异常拦截器捕获到该异常,同时记录一些日志。Spring 配置文件相关: 拦截器类:import org.aspectj.lang.ProceedingJoinPoint;import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;未来蓝图软件教育 http:/www.itfuture.org第 7 页 共 9 页import org.springframework.core.Ordered;import org.wllt.www.service.Loginfo
14、Service;public class EventLogInterceptor private LoginfoService service; public Object serviceIntercept(ProceedingJoinPoint point) throws Throwable if(point instanceof MethodInvocationProceedingJoinPoint) MethodInvocationProceedingJoinPoint mpoint = (MethodInvocationProceedingJoinPoint)point; / try
15、System.out.println(“记录日志开始“); service.saveLoginfo(“xtyhb“); System.out.println(“记录日志结束“); catch(Exception ex) ex.printStackTrace(); return null; public LoginfoService getService() return service;public void setService(LoginfoService service) this.service = service; 配置分析: 1、第一种配置情况配置如下:service 方法中的事务
16、传播属性都设为要求新建事务(REQUIRES_NEW),用户登录校验事务管理切面拦截器的 order 设为 1,而 log 拦截器的事务 order 设为 2,这意味着这两个要同时执行时,先执行用户登录校验事务拦截器,后执行 log 拦截器,由于事务管理是一个环绕通知(around) ,实际上是 log 拦截器被包围在帐号检验的事务管理拦截器中。结果如下:从结果中可以看出,log 异常拦截器在用户登录校验的事务回滚之前截获异常,在记录日志时,日志记录的 service 方法也在用户登录校验的事务管理之下,用户登录的事务还没有结束,根据 REQUIRES_NEW 特性,spring 会新开一个事
17、务,这时原来的数据库连接已经在一个事务中,一个连接不可能同时有两个事务,所以同时新创建一个 session 连接,日志记录就在新建的事务和 session 中进行,完了提交,并且会把新建的 session 连接关闭。 然后继续进行被中断的用户登录的事务管理操作,由于抛异常 spring 将用户登录的事务回未来蓝图软件教育 http:/www.itfuture.org第 8 页 共 9 页滚。 这样能够实现预想的功能,但是如果我去掉指定的 REQUIRES_NEW,那么 log 记录的操作会继续在用户登录的事务中进行,最后会被一起回滚。2、第二种配置情况配置如下:如果我把用户登录校验事务管理的
18、order 设为 2,log 拦截器的 order 设为 1,也就是 log 拦截器在事务管理拦截器的外面,会在 log 的 save 事务管理拦截器执行完了再执行 check 的异常事务管理结果如下:可以看出,用户登录的事务和日志记录的事务是前后两个不相关的事务,并且在日志记录事务中并不需要新建 session 连接。实际上这时也并不需要将 propagation 设为REQUIRES_NEW,使用默认的 REQUIRED 也照样能够正常工作。 所以应该将该异常拦截器设在事务管理拦截器的外面,即 log 拦截器的 order 设为 1,使异常拦截器引起的 log 事务排在前面。Transac
19、tion advice(环绕通知)Transaction adviceCheck 异常出现 logAspect(Exception)Check 用户检验方法XtyhbServiceEventLogInterceptor InterceptSaveLoginfoService抛出 Exception事务切面aop:aspect事务切面actionnsave未来蓝图软件教育 http:/www.itfuture.org第 9 页 共 9 页事务开始 回滚专业名词解释1、orderControls the ordering of the execution of this aspect when m
20、ultipleadvice executes at a specific joinpoint.2、propagation(如果不出现默认的是 propagation=” REQUIRES”)REQUIRES 表示传播事务REQUIRES_NEW 表示创建新的事务3、环绕通知 arroundbeginTransactiontrycheck();commitTransactioncatch(Exception e)rollbackTransactionCloseSession();4、advisoradvisor 是 spring aop 中的一个概念。advisor 可以翻译为增强器, 他是切入点(pointcut)和 advice 的适配器。 它有两部分组成:一个增强以及一个说明在何处增强的切入点。增强器完整的模块化了一个方面(因为一个方面,就是由在什么地方增强和怎么增强组成的) 。 增强和切入点可以复用。5、增强增强即 advice 在触发点触发时要做的动作