上篇说了aop的配置,并且说了spring事务管理是基于aop的,那么Spring声明式事务的配置就有两种方式:XML配置及注解配置
不多说,直接看配置文件
一、配置文件
applicationContext-transaction.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx.xsd ">
- <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
- <property name="sessionFactory" ref="sessionFactory" />
- </bean>
- <!-- 通知 -->
- <tx:advice id="txAdvice" transaction-manager="transactionManager">
- <tx:attributes>
- <!-- 传播行为 -->
- <tx:method name="save*" propagation="REQUIRED"/>
- <tx:method name="delete*" propagation="REQUIRED"/>
- <tx:method name="insert*" propagation="REQUIRED"/>
- <tx:method name="update*" propagation="REQUIRED"/>
- <tx:method name="list*" propagation="SUPPORTS" read-only="true"/>
- <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
- </tx:attributes>
- </tx:advice>
- <!-- aop -->
- <aop:config>
- <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.mango.jtt.service.*.*(..))"/>
- </aop:config>
- <!-- 注解管理事务 -->
- <tx:annotation-driven transaction-manager="transactionManager"/>
- </beans>
注解管理事务以上都是xml配置的事务,基于注解的事务,只需配置<tx:annotation-driven/>标签,然后在Spring bean中添加@Transational注解即可实现事务管理。
二,Spring事务管理本质
Spring并不直接管理事务,而是提供多种事务管理器,他们讲事务管理的职责委托给JAT或其他持久化机制所提供的平台相关的事务实现。上述配置文件中就是利用的hibernate事务管理器实现的Hibernate事务管理。详细信息不说,想事务属性什么的,具体可参考spring in action及spring官方文档
三、继续说下事务对getCurrentSession的影响
在Spring实战篇系列----源码解析SessionFactory及Session的管理及getCurrentSession的使用文章中说了getCurrentSession是要基于事务的,才能实现session的生命周期的管理。那么Spring的事务管理到底做了什么。
首先看事务管理器HibernateTransactionManager,它并没有做太多工作,一个空的构造函数及
- /**
- * Create a new HibernateTransactionManager instance.
- * A SessionFactory has to be set to be able to use it.
- * @see #setSessionFactory
- */
- public HibernateTransactionManager() {
- }
及afterPropertiesSet()方法
- @Override
- public void afterPropertiesSet() {
- if (getSessionFactory() == null) {
- throw new IllegalArgumentException("Property 'sessionFactory' is required");
- }
- if (this.entityInterceptor instanceof String && this.beanFactory == null) {
- throw new IllegalArgumentException("Property 'beanFactory' is required for 'entityInterceptorBeanName'");
- }
- // Check for SessionFactory's DataSource.
- if (this.autodetectDataSource && getDataSource() == null) {
- DataSource sfds = SessionFactoryUtils.getDataSource(getSessionFactory());
- if (sfds != null) {
- // Use the SessionFactory's DataSource for exposing transactions to JDBC code.
- if (logger.isInfoEnabled()) {
- logger.info("Using DataSource [" + sfds +
- "] of Hibernate SessionFactory for HibernateTransactionManager");
- }
- setDataSource(sfds);
- }
- }
- }
可见事务管理器的初始化并没有做太多工作。那么看事务管理对其的影响,先看调用栈
- TransactionSynchronizationManager.initSynchronization() line: 269
- HibernateTransactionManager(AbstractPlatformTransactionManager).prepareSynchronization(DefaultTransactionStatus, TransactionDefinition) line: 542
- HibernateTransactionManager(AbstractPlatformTransactionManager).prepareTransactionStatus(TransactionDefinition, Object, boolean, boolean, boolean, Object) line: 513
- HibernateTransactionManager(AbstractPlatformTransactionManager).getTransaction(TransactionDefinition) line: 393
- TransactionInterceptor(TransactionAspectSupport).createTransactionIfNecessary(PlatformTransactionManager, TransactionAttribute, String) line: 426
- TransactionInterceptor(TransactionAspectSupport).invokeWithinTransaction(Method, Class<?>, InvocationCallback) line: 275
- TransactionInterceptor.invoke(MethodInvocation) line: 96
- ReflectiveMethodInvocation.proceed() line: 179
- ExposeInvocationInterceptor.invoke(MethodInvocation) line: 92
- ReflectiveMethodInvocation.proceed() line: 179
- JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 213
- $Proxy316.getOrderById(String) line: not available
- OrderController.orderPay(String, Model) line: 84
从调用栈可以看出,只要在连接点处配置了事务管理,首先都会走到initSynchronization()。
- /**
- * Activate transaction synchronization for the current thread.
- * Called by a transaction manager on transaction begin.
- * @throws IllegalStateException if synchronization is already active
- */
- public static void initSynchronization() throws IllegalStateException {
- if (isSynchronizationActive()) {
- throw new IllegalStateException("Cannot activate transaction synchronization - already active");
- }
- logger.trace("Initializing transaction synchronization");
- synchronizations.set(new LinkedHashSet<TransactionSynchronization>());
- }
最终会在synchronizations中set进new LinkedHashSet<TransactionSynchronization>(),从而isSynchronizationActive()为true
- /**
- * Return if transaction synchronization is active for the current thread.
- * Can be called before register to avoid unnecessary instance creation.
- * @see #registerSynchronization
- */
- public static boolean isSynchronizationActive() {
- return (synchronizations.get() != null);
- }
因此这里也就解释了上上篇留下的疑问,为什么配置了事务管理,就不会抛异常了。其实只有配置了事务,session就会在事务提交或者回滚后关闭
- SessionImpl.close() line: 402
- SessionFactoryUtils.closeSession(Session) line: 167
- SpringSessionSynchronization.afterCompletion(int) line: 138
- TransactionSynchronizationUtils.invokeAfterCompletion(List<TransactionSynchronization>, int) line: 168
- HibernateTransactionManager(AbstractPlatformTransactionManager).invokeAfterCompletion(List<TransactionSynchronization>, int) line: 1001
- HibernateTransactionManager(AbstractPlatformTransactionManager).triggerAfterCompletion(DefaultTransactionStatus, int) line: 976
- HibernateTransactionManager(AbstractPlatformTransactionManager).processCommit(DefaultTransactionStatus) line: 806
- HibernateTransactionManager(AbstractPlatformTransactionManager).commit(TransactionStatus) line: 730
- TransactionInterceptor(TransactionAspectSupport).commitTransactionAfterReturning(TransactionAspectSupport$TransactionInfo) line: 483
- TransactionInterceptor(TransactionAspectSupport).invokeWithinTransaction(Method, Class<?>, InvocationCallback) line: 290
- TransactionInterceptor.invoke(MethodInvocation) line: 96
- ReflectiveMethodInvocation.proceed() line: 179
- ExposeInvocationInterceptor.invoke(MethodInvocation) line: 92
- ReflectiveMethodInvocation.proceed() line: 179
- JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 213
- $Proxy316.getOrderById(String) line: not available
- OrderController.orderPayInfo(String, Model) line: 72