一般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事務接口的交互。