Spring事务原理?事务在方法间如何传播?为什么会失效,年末阿里百度等大厂技术面试题汇总

registerJtaTransactionAspect(element, parserContext);
}
}
else {
// mode=“proxy”
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}

首先拿到mode属性的值判断是使用AspectJ生成代理还是JDK生成代理,这里我们主要看proxy模式,进入configureAutoProxyCreator方法:

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
// 注册AOP的入口类
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element);

// Create the TransactionAttributeSource definition.
// @Transactional注解的属性封装
RootBeanDefinition sourceDef = new RootBeanDefinition(
“org.springframework.transaction.annotation.AnnotationTransactionAttributeSource”);
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

// Create the TransactionInterceptor definition.
// AOP执行链
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
interceptorDef.setSource(eleSource);
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 拿到transaction-manager属性的值
registerTransactionManager(element, interceptorDef);
interceptorDef.getPropertyValues().add(“transactionAttributeSource”, new RuntimeBeanReference(sourceName));
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

// Create the TransactionAttributeSourceAdvisor definition.
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
advisorDef.setSource(eleSource);
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
advisorDef.getPropertyValues().add(“transactionAttributeSource”, new RuntimeBeanReference(sourceName));
advisorDef.getPropertyValues().add(“adviceBeanName”, interceptorName);
if (element.hasAttribute(“order”)) {
advisorDef.getPropertyValues().add(“order”, element.getAttribute(“order”));
}
parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
parserContext.registerComponent(compositeDef);
}
}

这里的流程比较长,但逻辑很简单。首先来看注册事务AOP入口类是哪个:

public static void registerAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {

// 将优先级更高的AOP入口类放入到IOC容器中
BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 设置代理生成的方式以及是否缓存代理类到当前线程
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}

主要看registerAutoProxyCreatorIfNecessary方法:

public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {

return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

Assert.notNull(registry, “BeanDefinitionRegistry must not be null”);

// 判断传进来的类和ICO中当前存在的类哪个优先级更高,将更高的放入IOC中
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}

//把AOP入口类封装成beanDefinition对象,要实例化
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add(“order”, Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//注解aop入口类的beanName名称 AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}

首先判断容器中是否已经存在AOP入口类,如果不存在则直接创建InfrastructureAdvisorAutoProxyCreator的BeanDefinition对象注册到容器中,这个类也是我之前分析的AOP入口类AbstractAutoProxyCreator的子类,再来看看其继承关系:

image

你会不会疑惑,这么多子类,到底会使用哪一个呢?回到刚刚的代码中,可以看到如果已经存在一个入口类了,就会通过findPriorityForClass获取两个类的优先级,最终就会使用优先级更大的那个,那么它们的优先级顺序是怎样的呢?

private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);

static {
// Set up the escalation list…
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}

private static int findPriorityForClass(@Nullable String className) {
// 索引即是优先级,越大优先级越高,IOC中只会存在一个事务AOP入口类
for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) {
Class<?> clazz = APC_PRIORITY_LIST.get(i);
if (clazz.getName().equals(className)) {
return i;
}
}
throw new IllegalArgumentException(
“Class name [” + className + “] is not a known auto-proxy creator class”);
}

可以看到,InfrastructureAdvisorAutoProxyCreator是优先级最低的,基本上不会起作用;AspectJAwareAdvisorAutoProxyCreator是当我们配置了aop:config标签时会注册,也就是xml配置的AOP的入口类;而AnnotationAwareAspectJAutoProxyCreator是当我们配置了aop:aspectj-autoproxy或使用@EnableAspectJAutoProxy注解时注册,因此大部分情况下都是使用的AnnotationAwareAspectJAutoProxyCreator。 注册完AOP的入口类后,回到configureAutoProxyCreator方法:

RootBeanDefinition sourceDef = new RootBeanDefinition(
“org.springframework.transaction.annotation.AnnotationTransactionAttributeSource”);
sourceDef.setSource(eleSource);
sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String sourceName =parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

AnnotationTransactionAttributeSource类的作用就是封装事务注解@Transactional的属性,这里需要记住其继承体系以及熟悉该类和其父类的属性和方法,对后面分析事物切面执行原理有帮助:

image

紧接着就是创建了TransactionInterceptor对象,专门的事务拦截器,并且该类是MethodInterceptor的子类,看到这个应该不陌生了,我们知道AOP调用链在执行过程中主要就是调用该类的invoke的方法,因此它是事务切面执行的入口。既然有了Interceptor,那么必不可少的还应该有Advisor,而Advisor又是由Advice和Poincut组成的,这样才能构成一个完整的切面,所以该方法后面就是创建这两个对象。以上就是xml配置AOP注解支持的原理,很简单,下面再来看看零配置又是如何实现的。

AOP零配置原理

使用过SpringBoot的都知道,如果需要开启事务注解的支持,只需要一个注解就能搞定:@EnableTransactionManagement,不用再配置xml文件,这个又是怎么做到的呢?不多说,我们直接来看其源码:

@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

boolean proxyTargetClass() default false;

AdviceMode mode() default AdviceMode.PROXY;

int order() default Ordered.LOWEST_PRECEDENCE;

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

最后

如果觉得本文对你有帮助的话,不妨给我点个赞,关注一下吧!

帮助,可以添加下面V无偿领取!(备注Java)**
[外链图片转存中…(img-FQBNxK8u-1711007211891)]

最后

如果觉得本文对你有帮助的话,不妨给我点个赞,关注一下吧!

[外链图片转存中…(img-986DQS3M-1711007211891)]

[外链图片转存中…(img-bzKNAdWI-1711007211891)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值