下面来看一下这2个类的代码。
AutoProxyRegistrar
这个类实现了ImportBeanDefinitionRegistrar接口,这个接口中有个方法registerBeanDefinitions
,spring容器在启动过程中会调用这个方法,开发者可以在这个方法中做一些bean注册的事情,而AutoProxyRegistrar在这个方法中主要做的事情就是下面@1
的代码,大家可以点进去看看,这里我就不点进去了,这个代码的作用就是在容器中做了一个非常关键的bean:InfrastructureAdvisorAutoProxyCreator,这个类之前在aop中介绍过,是bean后置处理器,会拦截所有bean的创建,对符合条件的bean创建代理。
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
Object mode = candidate.get(“mode”);
Object proxyTargetClass = candidate.get(“proxyTargetClass”);
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);//@1
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
}
}
说的简单点:AutoProxyRegistrar的作用就是启用spring aop的功能,对符合条件的bean创建代理。
ProxyTransactionManagementConfiguration
@Configuration(proxyBeanMethods = false)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
//注册bean:事务顾问(spring aop中拦截器链就是一个个的Advisor对象)
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource,
TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
//设置事务拦截器
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
//设置aop中事务拦截器的顺序
advisor.setOrder(this.enableTx.getNumber(“order”));
}
return advisor;
}
//注册bean:TransactionAttributeSource,TransactionAttributeSource用来获取获取事务属性配置信息:TransactionAttribute
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() { //@1
return new AnnotationTransactionAttributeSource();
}
//注册bean:事务拦截器
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(
TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
//拦截器中设置事务管理器,txManager可以为空
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
是个配置类,代码比较简单,注册了3个bean,最重要的一点就是添加了事务事务拦截器:TransactionInterceptor。
AutoProxyRegistrar负责启用aop的功能,而ProxyTransactionManagementConfiguration负责在aop中添加事务拦截器,二者结合起来的效果就是:对@Transaction标注的bean创建代理对象,代理对象中通过TransactionInterceptor拦截器来实现事务管理的功能。
再看下代码@1
,注册了一个TransactionAttributeSource类型的bean
TransactionAttributeSource接口源码:
public interface TransactionAttributeSource {
/**
* 确定给定的类是否是这个TransactionAttributeSource元数据格式中的事务属性的候选类。
* 如果此方法返回false,则不会遍历给定类上的方法,以进行getTransactionAttribute内省。
* 因此,返回false是对不受影响的类的优化,而返回true仅仅意味着类需要对给定类上的每个方法进行完全自省。
**/
default boolean isCandidateClass(Class<?> targetClass) {
return true;
}
//返回给定方法的事务属性,如果该方法是非事务性的,则返回null。
TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass);
}
getTransactionAttribute方法用来获取指定方法上的事务属性信息TransactionAttribute,大家对TransactionDefinition比较熟悉吧,用来配置事务属性信息的,而TransactionAttribute继承了TransactionDefinition接口,源码如下,而TransactionAttribute中新定义了2个方法,一个方法用来指定事务管理器bean名称的,一个用来判断给定的异常是否需要回滚事务
public interface TransactionAttribute extends TransactionDefinition {
//事务管理器的bean名称
@Nullable
String getQualifier();
//判断指定的异常是否需要回滚事务
boolean rollbackOn(Throwable ex);
}
TransactionAttributeSource接口有个实现类AnnotationTransactionAttributeSource,负责将@Transaction解析为TransactionAttribute对象,大家可以去这个类中设置一下断点看一下@Transaction注解查找的顺序,这样可以深入理解@Transaction放在什么地方才会让事务起效。
AnnotationTransactionAttributeSource内部最会委托给SpringTransactionAnnotationParser#parseTransactionAnnotation方法来解析@Transaction注解,进而得到事务属性配置信息:RuleBasedTransactionAttribute,代码如下:
org.springframework.transaction.annotation.SpringTransactionAnnotationParser
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
Propagation propagation = attributes.getEnum(“propagation”);
rbta.setPropagationBehavior(propagation.value());
Isolation isolation = attributes.getEnum(“isolation”);
rbta.setIsolationLevel(isolation.value());
rbta.setTimeout(attributes.getNumber(“timeout”).intValue());
rbta.setReadOnly(attributes.getBoolean(“readOnly”));
rbta.setQualifier(attributes.getString(“value”));
//回滚规则
List rollbackRules = new ArrayList<>();
for (Class<?> rbRule : attributes.getClassArray(“rollbackFor”)) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray(“rollbackForClassName”)) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (Class<?> rbRule : attributes.getClassArray(“noRollbackFor”)) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray(“noRollbackForClassName”)) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
rbta.setRollbackRules(rollbackRules);
return rbta;
}
下面来看重点了事务拦截器。
6、TransactionInterceptor
负责拦截@Transaction方法的执行,在方法执行之前开启spring事务,方法执行完毕之后提交或者回滚事务。
在讲这个类的源码之前,先提几个问题,大家带着问题去看代码,理解更深一些。
1、事务管理器是如何获取的?
2、什么情况下事务会提交?
3、什么异常会导致事务回滚?
6.1、invokeWithinTransaction方法
这个方法是事务拦截器的入口,需要spring管理事务的业务方法会被这个方法拦截,大家可以设置断点跟踪一下
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
TransactionAttributeSource tas = getTransactionAttributeSource();
//@6-1:获取事务属性配置信息:通过TransactionAttributeSource.getTransactionAttribute解析@Trasaction注解得到事务属性配置信息
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
//@6-2:获取事务管理器
final TransactionManager tm = determineTransactionManager(txAttr);
//将事务管理器tx转换为 PlatformTransactionManager
PlatformTransactionManager ptm = asPlatformTransactionManager™;
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// createTransactionIfNecessary内部,这里就不说了,内部主要就是使用spring事务硬编码的方式开启事务,最终会返回一个TransactionInfo对象
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
// 业务方法返回值
Object retVal;
try {
//调用aop中的下一个拦截器,最终会调用到业务目标方法,获取到目标方法的返回值
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
//6-3:异常情况下,如何走?可能只需提交,也可能只需回滚,这个取决于事务的配置
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
//清理事务信息
cleanupTransactionInfo(txInfo);
}
//6-4:业务方法返回之后,只需事务提交操作
commitTransactionAfterReturning(txInfo);
//返回执行结果
return retVal;
}
}
6.2、获取事务管理器
//@6-2:获取事务管理器
final TransactionManager tm = determineTransactionManager(txAttr);
determineTransactionManager源码如下:
org.springframework.transaction.interceptor.TransactionAspectSupport#determineTransactionManager
protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
// txAttr == null || this.beanFactory == null ,返回拦截器中配置的事务管理器
if (txAttr == null || this.beanFactory == null) {
return getTransactionManager();
}
//qualifier就是@Transactional注解中通过value或者transactionManager来指定事务管理器的bean名称
String qualifier = txAttr.getQualifier();
if (StringUtils.hasText(qualifier)) {
//从spring容器中查找[beanName:qualifier,type:TransactionManager]的bean
return determineQualifiedTransactionManager(this.beanFactory, qualifier);
}
else if (StringUtils.hasText(this.transactionManagerBeanName)) {
//从spring容器中查找[beanName:this.transactionManagerBeanName,type:TransactionManager]的bean
return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
}
else {
//最后通过类型TransactionManager在spring容器中找事务管理器
TransactionManager defaultTransactionManager = getTransactionManager();
if (defaultTransactionManager == null) {
defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
if (defaultTransactionManager == null) {
defaultTransactionManager = this.beanFactory.getBean(TransactionManager.class);
this.transactionManagerCache.putIfAbsent(
DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
}
}
return defaultTransactionManager;
}
}
从上面可知,事务管理器的查找顺序:
1、先看@Transactional中是否通过value或者transactionManager指定了事务管理器
2、TransactionInterceptor.transactionManagerBeanName是否有值,如果有,将通过这个值查找事务管理器
3、如果上面2种都没有,将从spring容器中查找TransactionManager类型的事务管理器
6.3、异常情况下,如何走?
try{
//…
}catch (Throwable ex) {
//6-3:异常情况下,如何走?可能只需提交,也可能只需回滚,这个取决于事务的配置
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
源码中可以看出,发生异常了会进入completeTransactionAfterThrowing
方法,completeTransactionAfterThrowing 源码如下
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
//@6-3-1:判断事务是否需要回滚
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
//通过事务管理器回滚事务
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
else {
//通过事务管理器提交事务
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
}
}
注意上面的@6-3-1
代码,判断事务是否需要回滚,调用的是transactionAttribute.rollbackOn(ex)
,最终会进入下面这个方法内部
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute#rollbackOn
最后:学习总结——MyBtis知识脑图(纯手绘xmind文档)
学完之后,若是想验收效果如何,其实最好的方法就是可自己去总结一下。比如我就会在学习完一个东西之后自己去手绘一份xmind文件的知识梳理大纲脑图,这样也可方便后续的复习,且都是自己的理解,相信随便瞟几眼就能迅速过完整个知识,脑补回来。下方即为我手绘的MyBtis知识脑图,由于是xmind文件,不好上传,所以小编将其以图片形式导出来传在此处,细节方面不是特别清晰。但可给感兴趣的朋友提供完整的MyBtis知识脑图原件(包括上方的面试解析xmind文档)
除此之外,前文所提及的Alibaba珍藏版mybatis手写文档以及一本小小的MyBatis源码分析文档——《MyBatis源码分析》等等相关的学习笔记文档,也皆可分享给认可的朋友!
etTransactionStatus());
}
}
}
注意上面的@6-3-1
代码,判断事务是否需要回滚,调用的是transactionAttribute.rollbackOn(ex)
,最终会进入下面这个方法内部
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute#rollbackOn
最后:学习总结——MyBtis知识脑图(纯手绘xmind文档)
学完之后,若是想验收效果如何,其实最好的方法就是可自己去总结一下。比如我就会在学习完一个东西之后自己去手绘一份xmind文件的知识梳理大纲脑图,这样也可方便后续的复习,且都是自己的理解,相信随便瞟几眼就能迅速过完整个知识,脑补回来。下方即为我手绘的MyBtis知识脑图,由于是xmind文件,不好上传,所以小编将其以图片形式导出来传在此处,细节方面不是特别清晰。但可给感兴趣的朋友提供完整的MyBtis知识脑图原件(包括上方的面试解析xmind文档)
[外链图片转存中…(img-RZxii4Gr-1714474363229)]
除此之外,前文所提及的Alibaba珍藏版mybatis手写文档以及一本小小的MyBatis源码分析文档——《MyBatis源码分析》等等相关的学习笔记文档,也皆可分享给认可的朋友!