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
和ProxyTransactionManagementConfiguration
2個元件,原始碼如下:
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的核心流程:
- 單例Bean初始化完成後執行後置處理器
AbstractAutoProxyCreator#postProcessAfterInitialization
方法- 在容器中找
Advisor
型別的所有增強器名稱,這就會將與事務相關的增強器BeanFactoryTransactionAttributeSourceAdvisor
找出來- 根據增強器名稱獲取對應的例項,並生成攔截鏈
- 判斷代理型別
- 根據不同的代理型別和攔截鏈建立代理物件
執行業務方法進行攔截
前面AOP說過不管理是JdkDynamicAopProxy
還是CglibAopProxy
代理,他們的執行最終都會去呼叫MethodInterceptor.invoke()
方法,而我們事務對應的方法攔截器是TransactionInterceptor
類。也就是說我們對事務的增強起始是在TransactionInterceptor
的invoke
方法中。原始碼如下:
@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;
}
// 程式設計式事務
...
}
從上面我們的原始碼可以看出,一個事務處理的標準流程:
createTransactionIfNecessary
建立一個事務invocation.proceedWithInvocation();
執行業務方法completeTransactionAfterThrowing(txInfo, ex);
如果遇到異常,事務回滾commitTransactionAfterReturning(txInfo);
如果沒有異常就提交事務
在建立,回滾和提交事務方法中還有的很多對巢狀事務的邏輯,比如事務的傳遞性,事務回滾的條件判斷等,這裡就不說了,有興趣自己