1. 程式人生 > >Spring 原始碼(七)Spring 事務

Spring 原始碼(七)Spring 事務

註冊後置處理器開啟對事務的支援

@EnableTransactionManagement

@EnableTransactionManagement註解的主要作用是開啟對事務的支援,原始碼如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

	boolean proxyTargetClass() default false;

	AdviceMode mode() default AdviceMode.PROXY;

	int order() default Ordered.LOWEST_PRECEDENCE;

}

這裡最核心的是TransactionManagementConfigurationSelector類,這個類主要的作用是通過ImportSelector註冊了AutoProxyRegistrar ProxyTransactionManagementConfiguration2個元件,原始碼如下:

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
				// 註冊 InfrastructureAdvisorAutoProxyCreator 後置處理器和事務管理器元件
				return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
			default:
				return null;
		}
	}
}

AutoProxyRegistrar

AutoProxyRegistrar 的主要作用是將InfrastructureAdvisorAutoProxyCreator後置處理器註冊到容器,註冊這個後置處理器和上一篇Spring AOP註冊AnnotationAwareAspectJAutoProxyCreator後置處理器一樣,這裡就不在重複說明了。InfrastructureAdvisorAutoProxyCreator 他是實現了BeanPostProcessor 介面的後置處理器,所以所有 Bean 的初始化都會呼叫其 postProcessAfterInitialization 方法,這個方法的實現是在其父類AbstractAutoProxyCreator類中。

ProxyTransactionManagementConfiguration

我們通過ProxyTransactionManagementConfiguration來註冊事務管理器元件,這個類本身也是一個配置類。在這個配置類中我們將會註冊一下三個元件:

  • BeanFactoryTransactionAttributeSourceAdvisor:事務增強器,包含了切面元件 TransactionInterceptor和標籤解析器TransactionAttributeSource
  • TransactionAttributeSource:@Transaction註解標籤解析器
  • TransactionInterceptor:儲存了事務屬性資訊,事務管理器;它本身也是一個方法攔截器,在invoke方法中進行了事務的處理。

建立代理Bean

上面我們說了所以所有 Bean 的初始化都會呼叫其 AbstractAutoProxyCreator#postProcessAfterInitialization 方法來完成Bean的增強,我們跟進去可以看到這段程式碼:

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
	if (bean != null) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		if (!this.earlyProxyReferences.contains(cacheKey)) {
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}

可以看到生代理物件是在wrapIfNecessary(bean, beanName, cacheKey);方法中完成的,原始碼如下:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	
	// 如果存在建言那麼久建立代理類
	// 獲取攔截鏈
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if (specificInterceptors != DO_NOT_PROXY) {
		this.advisedBeans.put(cacheKey, Boolean.TRUE);
		// 使用攔截鏈建立代理物件,對原有的Bean進行增強
		Object proxy = createProxy(
				bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
		this.proxyTypes.put(cacheKey, proxy.getClass());
		return proxy;
	}

	this.advisedBeans.put(cacheKey, Boolean.FALSE);
	return bean;
}

找到攔截鏈的的核心方法是 BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans方法

findAdvisorBeans:67, BeanFactoryAdvisorRetrievalHelper (org.springframework.aop.framework.autoproxy)
findCandidateAdvisors:102, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
findEligibleAdvisors:88, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
getAdvicesAndAdvisorsForBean:70, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
wrapIfNecessary:346, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
postProcessAfterInitialization:298, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
applyBeanPostProcessorsAfterInitialization:423, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
initializeBean:1638, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:555, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:483, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
getObject:312, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:308, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:761, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:867, AbstractApplicationContext (org.springframework.context.support)
refresh:543, AbstractApplicationContext (org.springframework.context.support)
<init>:84, AnnotationConfigApplicationContext (org.springframework.context.annotation)

原始碼如下:

public List<Advisor> findAdvisorBeans() {
	// Determine list of advisor bean names, if not cached already.
	String[] advisorNames = null;
	synchronized (this) {
		advisorNames = this.cachedAdvisorBeanNames;
		if (advisorNames == null) {
			// 獲取所有增強器的名稱
			advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
					this.beanFactory, Advisor.class, true, false);
			this.cachedAdvisorBeanNames = advisorNames;
		}
	}
	if (advisorNames.length == 0) {
		return new LinkedList<Advisor>();
	}

	List<Advisor> advisors = new LinkedList<Advisor>();
	for (String name : advisorNames) {
		if (isEligibleBean(name)) {
			if (this.beanFactory.isCurrentlyInCreation(name)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Skipping currently created advisor '" + name + "'");
				}
			}
			else {
				try {
					// 根據名稱增強器
					advisors.add(this.beanFactory.getBean(name, Advisor.class));
				}
				...
			}
		}
	}
	// 返回攔截鏈
	return advisors;
}

建立代理Bean的核心流程:

  1. 單例Bean初始化完成後執行後置處理器 AbstractAutoProxyCreator#postProcessAfterInitialization 方法
  2. 在容器中找Advisor型別的所有增強器名稱,這就會將與事務相關的增強器BeanFactoryTransactionAttributeSourceAdvisor找出來
  3. 根據增強器名稱獲取對應的例項,並生成攔截鏈
  4. 判斷代理型別
  5. 根據不同的代理型別和攔截鏈建立代理物件

執行業務方法進行攔截

前面AOP說過不管理是JdkDynamicAopProxy還是CglibAopProxy代理,他們的執行最終都會去呼叫MethodInterceptor.invoke()方法,而我們事務對應的方法攔截器是TransactionInterceptor類。也就是說我們對事務的增強起始是在TransactionInterceptorinvoke方法中。原始碼如下:

@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
	...
	return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
		@Override
		public Object proceedWithInvocation() throws Throwable {
			return invocation.proceed();
		}
	});
}

protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
			throws Throwable {

	// 獲取事務屬性
	final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
	// 獲取事務管理器
	final PlatformTransactionManager tm = determineTransactionManager(txAttr);
	// 構造方法唯一標示
	final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

	// 宣告式事務
	if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
		// 建立事務
		TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
		Object retVal = null;
		try {
			// 執行被增強的方法
			retVal = invocation.proceedWithInvocation();
		}
		catch (Throwable ex) {
			// 異常回滾
			completeTransactionAfterThrowing(txInfo, ex);
			throw ex;
		}
		finally {
			// 清除資訊
			cleanupTransactionInfo(txInfo);
		}
		// 提交事務
		commitTransactionAfterReturning(txInfo);
		return retVal;
	}
	// 程式設計式事務
	...
}

從上面我們的原始碼可以看出,一個事務處理的標準流程:

  1. createTransactionIfNecessary 建立一個事務
  2. invocation.proceedWithInvocation(); 執行業務方法
  3. completeTransactionAfterThrowing(txInfo, ex); 如果遇到異常,事務回滾
  4. commitTransactionAfterReturning(txInfo); 如果沒有異常就提交事務

在建立,回滾和提交事務方法中還有的很多對巢狀事務的邏輯,比如事務的傳遞性,事務回滾的條件判斷等,這裡就不說了,有興趣自己