一般Spring事务管理的配置都是XML或者声明式注解的方式,而后想要学习其运行的原理,从TransactionProxyFactoryBean深刻更合适。咱们从事务相关的核心类开始,逐步介绍Spring事务的运行机制。java
Spring事务的构成,基本有三个部分,事务属性的定义,事务对象及状态信息的持有,事务管理器的处理。spring
TransactionProxyFactoryBean实现了FactoryBean和InitializingBean接口,FactoryBean支持对须要事务支持的类的代理,InitializingBean初始化事务环境的准备工做,完成代理对象的建立。咱们再来看下xml的配置:编程
<!-- userManager事务代理类 --> <bean id="userManagerTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <!-- 原始对象 --> <property name="target" ref="userManager"/> <!-- 事务属性 --> <property name="transactionAttributes"> <props> <prop key="batchOperator">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> <!-- 事务管理器 --> <property name="transactionManager"> <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> </property> </bean>
须要配置的有三个,原始对象,事务属性和事务管理器。其中原始对象用来生成代理对象,而事务属性和事务管理器都设置到一个很重要的对象中,即TransactionInterceptor,事务拦截器,对应AOP中的加强类,完成事务管理和方法自己的结合。app
回到TransactionProxyFactoryBean的构造,其主要实现定义在抽象父类AbstractSingletonProxyFactoryBean中。在初始化方法afterPropertiesSet中,使用最原始的ProxyFactory, 完成了代理对象的建立。ide
AbstractSingletonProxyFactoryBean.java public void afterPropertiesSet() { if (this.target == null) { throw new IllegalArgumentException("Property 'target' is required"); } if (this.target instanceof String) { throw new IllegalArgumentException("'target' needs to be a bean reference, not a bean name as value"); } if (this.proxyClassLoader == null) { this.proxyClassLoader = ClassUtils.getDefaultClassLoader(); } // 建立AOP代理工厂 ProxyFactory proxyFactory = new ProxyFactory(); // 添加前置加强拦截器 if (this.preInterceptors != null) { for (Object interceptor : this.preInterceptors) { proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor)); } } // 核心加强拦截器,有子类实现,在TransactionProxyFactoryBean中便是TransactionInterceptor // Add the main interceptor (typically an Advisor). proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor())); // 添加后置加强拦截器 if (this.postInterceptors != null) { for (Object interceptor : this.postInterceptors) { proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor)); } } // 拷贝AOP的基本配置,如exposeProxy等 proxyFactory.copyFrom(this); // 设置原始对象 TargetSource targetSource = createTargetSource(this.target); proxyFactory.setTargetSource(targetSource); // 设置原始对象实现的接口 if (this.proxyInterfaces != null) { proxyFactory.setInterfaces(this.proxyInterfaces); } else if (!isProxyTargetClass()) { // Rely on AOP infrastructure to tell us what interfaces to proxy. Class<?> targetClass = targetSource.getTargetClass(); if (targetClass != null) { proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader)); } } // 对proxyFactory的后置处理 postProcessProxyFactory(proxyFactory); // 代理工厂生成代理对象 this.proxy = proxyFactory.getProxy(this.proxyClassLoader); }
其中核心加强拦截器有子类实现其建立方法createMainInterceptorpost
TransactionProxyFactoryBean.java protected Object createMainInterceptor() { // 初始化TransactionInterceptor this.transactionInterceptor.afterPropertiesSet(); if (this.pointcut != null) { // 有pointcut的生成DefaultPointcutAdvisor return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor); } else { // Rely on default pointcut. // 没有pointcut的依赖默认的pointcut return new TransactionAttributeSourceAdvisor(this.transactionInterceptor); } }
TransactionAttributeSourceAdvisor的默认pointcut类是TransactionAttributeSourcePointcut,定义在其内部。学习
TransactionAttributeSourceAdvisor.java private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() { @Override @Nullable protected TransactionAttributeSource getTransactionAttributeSource() { return (transactionInterceptor != null ? transactionInterceptor.getTransactionAttributeSource() : null); } };
TransactionAttributeSourcePointcut是一个抽象类,在TransactionAttributeSourceAdvisor匿名实现的。咱们来看下TransactionAttributeSourcePointcut的实现,它继承了StaticMethodMatcherPointcut,一个对方法进行匹配的基本Pointcut类,实现matches方法。ui
public boolean matches(Method method, @Nullable Class<?> targetClass) { if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) { return false; } // 获取事务属性数据源 TransactionAttributeSource tas = getTransactionAttributeSource(); // 根据方法和Class对象获取是否有事务属性配置存在,来决定是否切入事务AOP return (tas == null || tas.getTransactionAttribute(method, targetClass) != null); }
而事务属性数据源从哪里设置的呢?咱们在上面的TransactionAttributeSourceAdvisor匿名实现的TransactionAttributeSourcePointcut类中能够发现TransactionAttributeSource是从TransactionInterceptor中获取的。而TransactionInterceptor的TransactionAttributeSource是哪里设置的呢?来源于XML配置的properties对象transactionAttributes,在TransactionProxyFactoryBean的setTransactionAttributes方法中。this
public void setTransactionAttributes(Properties transactionAttributes) { this.transactionInterceptor.setTransactionAttributes(transactionAttributes); }
transactionAttributes实际被设置到TransactionInterceptor中线程
public void setTransactionAttributes(Properties transactionAttributes) { NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource(); tas.setProperties(transactionAttributes); this.transactionAttributeSource = tas; }
这里看到TransactionAttributeSource的实现是NameMatchTransactionAttributeSource。在其内部维护了一个方法名和事务属性的Map
private Map<String, TransactionAttribute> nameMap = new HashMap<>();
所以对哪一个方法进行事务AOP的切入的原理就很清楚了。接下来就是核心拦截器TransactionInterceptor的解析。
TransactionInterceptor实现了Spring AOP的基本增长接口MethodInterceptor,实现invoke方法
public Object invoke(final MethodInvocation invocation) throws Throwable { // Work out the target class: may be {@code null}. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // Adapt to TransactionAspectSupport's invokeWithinTransaction... return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); }
具体实现由TransactionInterceptor抽象子类TransactionAspectSupport的invokeWithinTransaction方法执行
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // If the transaction attribute is null, the method is non-transactional. // 获取事务属性数据源,若是为null,则此方法为非事务环境 TransactionAttributeSource tas = getTransactionAttributeSource(); // 获取事务属性 final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); // 根据事务属性决定事务管理器对象 final PlatformTransactionManager tm = determineTransactionManager(txAttr); // 链接点标识,通常就是方法名 final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. // 建立事务对象,并返回事务信息 TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; // 环绕加强实现,try中为方法自己的执行 try { // This is an around advice: Invoke the next interceptor in the chain. // This will normally result in a target object being invoked. retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { // target invocation exception // 异常后的事务处理 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { // 解绑事务信息和当前线程 cleanupTransactionInfo(txInfo); } // 方法执行成功后事务提交的处理 commitTransactionAfterReturning(txInfo); return retVal; } // ...
这个方法就是事务执行的核心部分,经过环绕增长,完成方法不一样执行结果(成功或异常)对应事务的处理。固然前提是要先建立事务,来看createTransactionIfNecessary方法
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, final String joinpointIdentification) { // If no name specified, apply method identification as transaction name. if (txAttr != null && txAttr.getName() == null) { txAttr = new DelegatingTransactionAttribute(txAttr) { @Override public String getName() { return joinpointIdentification; } }; } TransactionStatus status = null; if (txAttr != null) { if (tm != null) { // 由事务管理器建立事务状态对象 status = tm.getTransaction(txAttr); } else { if (logger.isDebugEnabled()) { logger.debug("Skipping transactional joinpoint [" + joinpointIdentification + "] because no transaction manager has been configured"); } } } // 填充事务状态对象的其余信息 return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); }
事务对象及状态的维护由具体的事务管理器来管理,下一章咱们具体讨论事务管理器,这里主要关注它的构建骨架。返回的事务状态对象TransactionStatus,须要再次被prepareTransactionInfo方法填充
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, String joinpointIdentification, @Nullable TransactionStatus status) { // 建立事务信息对象,记录事务管理器,事务属性,及事务切入点信息 TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification); if (txAttr != null) { // 记录事务状态 txInfo.newTransactionStatus(status); } else { if (logger.isTraceEnabled()) logger.trace("Don't need to create transaction for [" + joinpointIdentification + "]: This method isn't transactional."); } // We always bind the TransactionInfo to the thread, even if we didn't create // a new transaction here. This guarantees that the TransactionInfo stack // will be managed correctly even if no transaction was created by this aspect. // 绑定事务信息对象和当前线程,并在当前事务信息对象中记录线程原来绑定的事务信息对象,从而保证了事务信息栈的管理 txInfo.bindToThread(); return txInfo; }
这里很是重要的是维护了一个线程级别的事务信息的栈结构。
事务信息组建完成后,就是方法自己的执行。若是发生异常,则事务该如何处理,由completeTransactionAfterThrowing方法执行
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) { if (txInfo != null && txInfo.getTransactionStatus() != null) { if (logger.isTraceEnabled()) { logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex); } // 校验当前异常是否要回滚事务,若是是,则执行回滚操做,若是不是,则执行提交操做 if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) { try { txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus()); } catch (TransactionSystemException ex2) { logger.error("Application exception overridden by rollback exception", ex); ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException ex2) { logger.error("Application exception overridden by rollback exception", ex); throw ex2; } catch (Error err) { logger.error("Application exception overridden by rollback error", ex); throw err; } } else { // We don't roll back on this exception. // Will still roll back if TransactionStatus.isRollbackOnly() is true. try { txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } catch (TransactionSystemException ex2) { logger.error("Application exception overridden by commit exception", ex); ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException ex2) { logger.error("Application exception overridden by commit exception", ex); throw ex2; } catch (Error err) { logger.error("Application exception overridden by commit error", ex); throw err; } } } }
在上面的方法中,核心就是判断原始方法抛出的异常是否要回滚事务,若是是,则调用事务管理器回滚事务,若是不是,则直接提交事务。
对异常是否回滚事务的判断是由事务属性中的rollbackFor和noRollbackFor共同决定的,默认都没有配置时,执行DefaultTransactionAttribute基本事务属性类中的rollbackOn方法
public boolean rollbackOn(Throwable ex) { return (ex instanceof RuntimeException || ex instanceof Error); }
即当异常为运行时异常或Error时,就会回滚,不然直接提交。直接提交这一点也是须要格外注意的。
若是方法运行没有异常,执行完成后,就须要提交事务,由commitTransactionAfterReturning方法执行
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) { if (txInfo != null && txInfo.getTransactionStatus() != null) { if (logger.isTraceEnabled()) { logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]"); } txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } }
调用事务管理器执行commit来提交事务。
至此,对于TransactionProxyFactoryBean的AOP代理生成以及TransactionInterceptor核心加强中事务执行的原理都基本解析清楚了,下一章介绍事务管理器的运行机制以及DataSourceTransactionManager如何和JDBC事务接口的交互。