上節(jié)我們通過簡單的案例來熟悉了spring注解版的聲明式事務(wù)的開發(fā),其實大家可以分別測一下,當(dāng)我們不配置事務(wù)管理以及不貼注解EnableTransactionManagement時我們執(zhí)行邏輯時是否會插入記錄到數(shù)據(jù)庫中,答案不行的,注解EnableTransactionManagement的主要目的是開啟事務(wù)的功能,接下來的學(xué)習(xí)我們來圍繞它進行
EnableTransactionManagement
點進去之后發(fā)現(xiàn)此注解位于org.springframework.transaction.annotation包下,具體代碼片段如下:
@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 2147483647;
}
看到上述的代碼我相信大家都不陌生,spring 的注解開發(fā)的套路,還是給我們的容器中導(dǎo)入一個組件【TransactionManagementConfigurationSelector】,接下來的核心就是它了
TransactionManagementConfigurationSelector
簡單的說這個組件的作用是作為一個事務(wù)配置管理的選擇器來出現(xiàn)幫助我們都做了什么事,方法進去我們發(fā)下如下的代碼片段:
protected String[] selectImports(AdviceMode adviceMode) {
switch(adviceMode) {
case PROXY:
return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[]{this.determineTransactionAspectClass()};
default:
return null;
}
}
其中通過傳入的參數(shù)判斷你到底是那種類型的,并為我們導(dǎo)入其對應(yīng)的組件,我們這里是PROXY此類型的,為啥這么肯定了,在我們的EnableTransactionManagement 注解類中默認(rèn)的就是它,大家可以在開頭的代碼片段中看到,是PROXY類型,這里幫我們導(dǎo)入的是AutoProxyRegistrar和ProxyTransactionManagementConfiguration這兩個組件,分別來看:
AutoProxyRegistrar
該類實現(xiàn)了ImportBeanDefinitionRegistrar接口,也就是說其主要的作用是幫我們給容器注冊其組件,接下來我們通過方法#registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) 來看幫我們注冊的具體是那個組件
- 1.首先通過如下的代碼操作獲取當(dāng)前的當(dāng)前容器的類型【AdviceMode:屬于JDK的代理】
Object mode = candidate.get("mode");
前面我們已經(jīng)知道了是PROXY類型的,所以接著看如下的代碼片段:
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode == AdviceMode.PROXY) {
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean)proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
這里有兩個判斷,來看下:
- 如果當(dāng)前獲取到了有proxyTargetClass【代理目標(biāo)對象】時,會去執(zhí)行方法AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry),很顯然我們這里是不會調(diào)用的,在我們的注解類EnableTransactionManagement中proxyTargetClass的獲取默認(rèn)就是false,代碼如下:
boolean proxyTargetClass() default false;
所以我們直接來分析方法AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, (Object)null);
}
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
從上面的代碼我們可以看到的是AutoProxyRegistrar幫我們想容器注冊了一個InfrastructureAdvisorAutoProxyCreator【基礎(chǔ)的自動代理增強創(chuàng)建器】,看到這個是不是跟我們Aop中【AspectJAwareAdvisorAutoProxyCreator】這個有點相似,其實質(zhì)是一樣的,只不過是事務(wù)中幫我們注冊的是InfrastructureAdvisorAutoProxyCreator此類型的,我們看看它的作用:
InfrastructureAdvisorAutoProxyCreator
該類位于org.springframework.aop.framework.autoproxy包下,其繼承實現(xiàn)關(guān)系如下圖所示:

不難發(fā)現(xiàn)InfrastructureAdvisorAutoProxyCreator實質(zhì)也是一個【InstantiationAwareBeanPostProcessor】類型的后置處理器,那作為后置處理器的話,我們已經(jīng)清楚的知道了它的作用:
幫助我們完成對象的創(chuàng)建
將創(chuàng)建完成的對象進行包裝------> 返回其對應(yīng)的代理對象
獲取攔截器鏈并進行相應(yīng)的轉(zhuǎn)化為一個個的攔截器
利用攔截器機制進行鏈?zhǔn)降膱?zhí)行我們的目標(biāo)方法
下面的代碼是具體的注冊過程:
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
} else {
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", -2147483648);
beanDefinition.setRole(2);
registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
return beanDefinition;
}
}
上述就是AutoProxyRegistrar組件幫我們所做的事,接下來我們來看看另外一個組件
ProxyTransactionManagementConfiguration
該類位于org.springframework.transaction.annotation包下,其實質(zhì)也是一個配置類,該容器注冊一些組件,這些組件有 transactionAdvisor 【事務(wù)增強器】和transactionInterceptor【事務(wù)攔截器】 ,具體注冊的邏輯代碼如下:
- transactionAdvisor 【事務(wù)增強器】
@Bean(
name = {"org.springframework.transaction.config.internalTransactionAdvisor"}
)
@Role(2)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder((Integer)this.enableTx.getNumber("order"));
}
return advisor;
}
- transactionInterceptor【事務(wù)攔截器】
@Bean
@Role(2)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
其中在注冊組件的過程中我們發(fā)現(xiàn)會有這樣一個屬性TransactionAttributeSource【事務(wù)屬性源】,同樣也是注冊進來的
@Bean
@Role(2)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
進去方法來到AnnotationTransactionAttributeSource類【事務(wù)注解的屬性】,其中方法#AnnotationTransactionAttributeSource(boolean publicMethodsOnly)需要我們注意一點
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
if (!jta12Present && !ejb3Present) {
this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
} else {
this.annotationParsers = new LinkedHashSet(4);
this.annotationParsers.add(new SpringTransactionAnnotationParser());
if (jta12Present) {
this.annotationParsers.add(new JtaTransactionAnnotationParser());
}
if (ejb3Present) {
this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
}
}
}
方法主要是當(dāng)前是那種類型的事務(wù)并進行解釋其對應(yīng)的事務(wù)注解信息,當(dāng)然這里用的是spring的自己的事務(wù),也就是如下代碼:
if (!jta12Present && !ejb3Present) {
this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
} else {
this.annotationParsers = new LinkedHashSet(4);
this.annotationParsers.add(new SpringTransactionAnnotationParser());
接著我們看到是通過SpringTransactionAnnotationParser【事務(wù)注解解析器】來幫助我們解析具體的注解信息,進去來到類SpringTransactionAnnotationParser#parseTransactionAnnotation(AnnotationAttributes attributes)方法來完成事務(wù)注解的解析過程,解析之前還是有一步重要的動作來看方法
@Override
@Nullable
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
這段代碼很簡單,無非就是先拿到我們的注解類Transactional【事務(wù)注解】然后封裝成一個注解屬性【AnnotationAttributes 】,接著調(diào)用我們的具體解析方法,Transactional具體都有哪些屬性我們來看看:
public @interface Transactional {
@AliasFor("transactionManager")
String value() default "";
@AliasFor("value")
String transactionManager() default "";
Propagation propagation() default Propagation.REQUIRED;
Isolation isolation() default Isolation.DEFAULT;
int timeout() default -1;
boolean readOnly() default false;
Class<? extends Throwable>[] rollbackFor() default {};
String[] rollbackForClassName() default {};
Class<? extends Throwable>[] noRollbackFor() default {};
String[] noRollbackForClassName() default {};
}
上述的這些屬性我們都是可以配置的如:
@Service
public class UserService {
@Resource
private UserDao userDao;
@Transactional(propagation = Propagation.REQUIRED ,isolation = Isolation.DEFAULT,timeout = 1)
public void insert(){
userDao.insert();
System.out.println("插入成功....");
int i = 10 / 0;
}
感興趣的可以自己玩玩,既然我們已經(jīng)到AnnotationTransactionAttributeSource的作用,回到我們分析的入口類ProxyTransactionManagementConfiguration
我們在方法#transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor)中
給容器中注冊了一個BeanFactoryTransactionAttributeSourceAdvisor【事務(wù)增強器】
接著事務(wù)增強器保存我們前面分析的事務(wù)注解信息
保存事務(wù)攔截器到事務(wù)增強器中
最后進行排序操作
期間我們用到了事務(wù)攔截器,那么我們來看看這事務(wù)攔截器的作用
TransactionInterceptor
該類位于org.springframework.transaction.interceptor包下,發(fā)下該類實現(xiàn)了MethodInterceptor接口,代碼片段如下:
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
public TransactionInterceptor() {
}
還記得我們在Aop目標(biāo)方法分析時,有一步就是將每一個攔截器包裝成一個MethodInterceptor類型的攔截器,其實看到這里我們的事務(wù)攔截器的跟Aop的原理是類似的,接著回到我們的TransactionInterceptor類中#invoke(MethodInvocation invocation)方法
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null;
Method var10001 = invocation.getMethod();
invocation.getClass();
return this.invokeWithinTransaction(var10001, targetClass, invocation::proceed);
}
其中方法#invokeWithinTransaction(....)執(zhí)行目標(biāo)類的,進去我們來到l類TransactionAspectSupport中的#invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, TransactionAspectSupport.InvocationCallback invocation)方法,具體看看方法做了哪些處理:
- 首先獲取事務(wù)注解屬性
TransactionAttributeSource tas = this.getTransactionAttributeSource();
TransactionAttribute txAttr = tas != null ? tas.getTransactionAttribute(method, targetClass) : null;
上述只是做鋪墊,接下來我們來看重頭戲,是如何獲取我們的事務(wù)管理器的,代碼片段如下:
TransactionManager tm = this.determineTransactionManager(txAttr);
繼續(xù)跟蹤代碼來到方法#determineTransactionManager(@Nullable TransactionAttribute txAttr)
@Nullable
protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
if (txAttr != null && this.beanFactory != null) {
String qualifier = txAttr.getQualifier();
if (StringUtils.hasText(qualifier)) {
return this.determineQualifiedTransactionManager(this.beanFactory, qualifier);
} else if (StringUtils.hasText(this.transactionManagerBeanName)) {
return this.determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
} else {
TransactionManager defaultTransactionManager = this.getTransactionManager();
if (defaultTransactionManager == null) {
defaultTransactionManager = (TransactionManager)this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
if (defaultTransactionManager == null) {
defaultTransactionManager = (TransactionManager)this.beanFactory.getBean(TransactionManager.class);
this.transactionManagerCache.putIfAbsent(DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
}
}
return defaultTransactionManager;
}
} else {
return this.getTransactionManager();
}
}
上述代碼主要的操作是通過不同的方式去獲取我們的事務(wù)管理器實例,分別來看:
- 1.通過注解 @Qualifier去獲取
String qualifier = txAttr.getQualifier();
if (StringUtils.hasText(qualifier)) {
return this.determineQualifiedTransactionManager(this.beanFactory, qualifier);
方法進去來到具體是如何實現(xiàn)的過程:
private PlatformTransactionManager determineQualifiedTransactionManager(BeanFactory beanFactory, String qualifier) {
PlatformTransactionManager txManager = asPlatformTransactionManager(this.transactionManagerCache.get(qualifier));
if (txManager == null) {
txManager = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
beanFactory, PlatformTransactionManager.class, qualifier);
this.transactionManagerCache.putIfAbsent(qualifier, txManager);
}
return txManager;
}
- 方式二:通過bean的名字去獲取
else {
TransactionManager defaultTransactionManager = this.getTransactionManager();
if (defaultTransactionManager == null) {
defaultTransactionManager = (TransactionManager)this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
if (defaultTransactionManager == null) {
defaultTransactionManager = (TransactionManager)this.beanFactory.getBean(TransactionManager.class);
this.transactionManagerCache.putIfAbsent(DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
}
}
很顯然我們是自己配置的事務(wù)管理器,所以是通過方式二的去獲取事務(wù)管理器的,既然我們了解了事務(wù)管理器的獲取過程,回到我們的方法#invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, TransactionAspectSupport.InvocationCallback invocation)接著看:
- 接著獲取我們的PlatformTransactionManager
PlatformTransactionManager ptm = this.asPlatformTransactionManager(tm);
前提是之前沒有添加指定任何transactionmanger最終會從容器中按照類型獲取一個PlatformTransactionManager
- 最后執(zhí)行我們的目標(biāo)方法
- 如果是正常的情況下直接提交事務(wù)
private Mono<Void> commitTransactionAfterReturning(@Nullable TransactionAspectSupport.ReactiveTransactionInfo txInfo) {
if (txInfo != null && txInfo.getReactiveTransaction() != null) {
if (TransactionAspectSupport.this.logger.isTraceEnabled()) {
TransactionAspectSupport.this.logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
return txInfo.getTransactionManager().commit(txInfo.getReactiveTransaction());
} else {
return Mono.empty();
}
}
2.如果有異常的話,進行事務(wù)回滾
private Mono<Void> completeTransactionAfterThrowing(@Nullable TransactionAspectSupport.ReactiveTransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.getReactiveTransaction() != null) {
if (TransactionAspectSupport.this.logger.isTraceEnabled()) {
TransactionAspectSupport.this.logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex);
}
return txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex) ? txInfo.getTransactionManager().rollback(txInfo.getReactiveTransaction()).onErrorMap((ex2) -> {
TransactionAspectSupport.this.logger.error("Application exception overridden by rollback exception", ex);
if (ex2 instanceof TransactionSystemException) {
((TransactionSystemException)ex2).initApplicationException(ex);
}
return ex2;
}) : txInfo.getTransactionManager().commit(txInfo.getReactiveTransaction()).onErrorMap((ex2) -> {
TransactionAspectSupport.this.logger.error("Application exception overridden by commit exception", ex);
if (ex2 instanceof TransactionSystemException) {
((TransactionSystemException)ex2).initApplicationException(ex);
}
return ex2;
});
} else {
return Mono.empty();
}
}
可以發(fā)現(xiàn)的是,不管是事務(wù)提交還是回滾操作,都是通過我們的事務(wù)管理器來完成,到這里我們的聲明式事務(wù)的相關(guān)源碼分析已完成