Spring源码剖析-事务源码之@Transactionl解析

AnnotationDrivenBeanDefinitionParser创建AutoProxyCreator


看得出来上面的 init 方法中注册了一个 AnnotationDrivenBeanDefinitionParser 它就是针对于 <tx:annotation-driven/>的解析器,并且负责创建事务管理需要的基础类。

class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {

AnnotationDrivenBeanDefinitionParser() {

}

//解析元素:Element就是 tx:annotation-driven/

public BeanDefinition parse(Element element, ParserContext parserContext) {

//注册事务监听

this.registerTransactionalEventListenerFactory(parserContext);

//判断model,默认是proxy,走else

String mode = element.getAttribute(“mode”);

if (“aspectj”.equals(mode)) {

this.registerTransactionAspect(element, parserContext);

} else {

//创建自动代理创建器(InfrastructureAdvisorAutoProxyCreator)

AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);

}

return null;

}

AopAutoProxyConfigurer 创建事务核心类


这个parse解析方法注册了事务监听器后就判断了mode,默认使用的是proxy代理方式,即调用configureAutoProxyCreator方法,一路跟下去

/**

  • Inner class to just introduce an AOP framework dependency when actually in proxy mode.

*/

private static class AopAutoProxyConfigurer {

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {

//注册一个自动代理创建器 InfrastructureAdvisorAutoProxyCreator

AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;

//判断容器中是否已经注册了 internalTransactionAdvisor

if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {

Object eleSource = parserContext.extractSource(element);

//【标记1】注册 TransactionAttributeSource

// Create the TransactionAttributeSource definition.

RootBeanDefinition sourceDef = new RootBeanDefinition(

“org.springframework.transaction.annotation.AnnotationTransactionAttributeSource”);

sourceDef.setSource(eleSource);

sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

//【标记2】注册 TransactionInterceptor

// Create the TransactionInterceptor definition.

RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);

interceptorDef.setSource(eleSource);

interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

registerTransactionManager(element, interceptorDef);

interceptorDef.getPropertyValues().add(“transactionAttributeSource”, new RuntimeBeanReference(sourceName));

String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

//【标记3】 注册一个TransactionAttributeSourceAdvisor

// Create the BeanFactoryTransactionAttributeSourceAdvisor 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);

}

}

}

该方法先是创建了一个 InfrastructureAdvisorAutoProxyCreator 代理创建器 ,然后又注册了 AnnotationTransactionAttributeSourceTransactionInterceptorBeanFactoryTransactionAttributeSourceAdvisor 三个Bean , 且前两个Bean被添加到了 BeanFactoryTransactionAttributeSourceAdvisor 中。

  • InfrastructureAdvisorAutoProxyCreator:是BeanPostProcessor的子类,在Bean的初始化之后调用postProcessAfterInitialization方法,目的就是找出增强器为合适的类创建代理。跟上一章节《AOP原理》做的事情差不多

  • AnnotationTransactionAttributeSource : 是专门用于获取基于注解的Spring声明式事务管理的事务属性的属性源,用来读取@Transational注解并进行相关参数封装,用做后续的事务处理。

它除了能处理Transactional注解之外,还支持JTA 1.2的javax.transaction.Transactional事务注解以及EJB3的javax.ejb.TransactionAttribute事务注解

  • TransactionInterceptor:该类实现了TransactionAspectSupport , TransactionAspectSupport 中持有 TransactionManager ,拥有处理事务的能力。同时该类还实现了 MethodInterceptor 接口 ,它也作为AOP的拦截器。拦截器链中每个拦截器都有一个invoke方法,该方法就是对某个方法进行事务增强的入口,因此主要看invoke方法的实现逻辑!

  • BeanFactoryTransactionAttributeSourceAdvisor:它是一个Advisor,用来对事务方法做增强,只要被注解@Transationl的方法都会被增强,该Advisor 包含 AnnotationTransactionAttributeSource 和 TransactionInterceptor ,以及 TransactionAttributeSourcePointcut 。

TransactionAttributeSourcePointcut 是事务属性源匹配器,是BeanFactoryTransactionAttributeSourceAdvisor的切入点,通过它来判断某个bean是否可以被增强

在这里插入图片描述

解析当前方法是否要被代理

==========================================================================

InfrastructureAdvisorAutoProxyCreator是一个BeanPostProcessor,当Bean在实例化过程中,会通过AutoProxyCreator的postProcessAfterInitialization方法来决定是否创建代理,其实就是通过BeanFactoryTransactionAttributeSourceAdvisor 来解析判断该类是否被注解了@Transcational来决定是否创建代理 ,见:AbstractAutoProxyCreator#wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {

if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {

return bean;

} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {

return bean;

} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {

//获取增强器 Advisors

Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);

if (specificInterceptors != DO_NOT_PROXY) {

this.advisedBeans.put(cacheKey, Boolean.TRUE);

//创建代理

Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

this.proxyTypes.put(cacheKey, proxy.getClass());

return proxy;

} else {

this.advisedBeans.put(cacheKey, Boolean.FALSE);

return bean;

}

} else {

this.advisedBeans.put(cacheKey, Boolean.FALSE);

return bean;

}

}

AbstractAdvisorAutoProxyCreator查找增强器


通过调用 AbstractAdvisorAutoProxyCreator#findCandidateAdvisors ,查找增强器 ,通过AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply 来匹配当前类适合的增强器,然后为当前Bean创建代理。这个流程在上一章: 《AOP原理》 已经说过,这里就不细细分析了。见:AbstractAdvisorAutoProxyCreator#findEligibleAdvisors

protected List findEligibleAdvisors(Class<?> beanClass, String beanName) {

//查找所有增强器

List candidateAdvisors = this.findCandidateAdvisors();

//找到当前beanClass适用的增强器

List eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);

this.extendAdvisors(eligibleAdvisors);

if (!eligibleAdvisors.isEmpty()) {

eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);

}

return eligibleAdvisors;

}

我们重点来看一下它是如何匹配适合当前Bean的增强器的。见:

AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply

//搜索能应用于当前beanClass的 Advisors

protected List findAdvisorsThatCanApply(

List candidateAdvisors, Class<?> beanClass, String beanName) {

ProxyCreationContext.setCurrentProxiedBeanName(beanName);

try {

return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);

}

finally {

ProxyCreationContext.setCurrentProxiedBeanName(null);

}

}

这里的 candidateAdvisors 就是获取到的增强器 ,其中就包括:BeanFactoryTransactionAttributeSourceAdvisor , beanClass是当前要被创建代理的类,然后走的是AopUtils.findAdvisorsThatCanApply 方法查找能匹配当前类的advisors.一路断点跟下去会走到 AopUtils#canApply

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {

if (advisor instanceof IntroductionAdvisor) {

return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);

}

else if (advisor instanceof PointcutAdvisor) {

//转换成 PointcutAdvisor 切点的Advisor

PointcutAdvisor pca = (PointcutAdvisor) advisor;

return canApply(pca.getPointcut(), targetClass, hasIntroductions);

}

else {

// It doesn’t have a pointcut so we assume it applies.

return true;

}

}

AopUtils 查找合适的增强器


继续跟踪 org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean) 源码:

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {

Assert.notNull(pc, “Pointcut must not be null”);

//class 过滤器 ,默认直接返回true

if (!pc.getClassFilter().matches(targetClass)) {

return false;

}

//方法匹配器,其实就是 BeanFactoryTransactionAttributeSourceAdvisor

MethodMatcher methodMatcher = pc.getMethodMatcher();

if (methodMatcher == MethodMatcher.TRUE) {

// No need to iterate the methods if we’re matching any method anyway…

return true;

}

IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;

if (methodMatcher instanceof IntroductionAwareMethodMatcher) {

introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;

}

//获取到要被创建代理的原生类的 class,并把其接口添加到classes中

Set<Class<?>> classes = new LinkedHashSet<>();

if (!Proxy.isProxyClass(targetClass)) {

classes.add(ClassUtils.getUserClass(targetClass));

}

classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

//处理classes

for (Class<?> clazz : classes) {

//拿到原生类,或其接口的所有方法声明

Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);

for (Method method : methods) {

//通过 MethodMatcher 匹配,走的是 TransactionAttributeSourcePointcut#matches方法

if (introductionAwareMethodMatcher != null ?

introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :

methodMatcher.matches(method, targetClass)) {

return true;

}

}

}

return false;

}

该方法的作用是匹配给定的切入点是否完全适用于给定的类,通过MethodMatcher 来匹配,这里的MethodMatcher 本身就是PointBeanFactoryTransactionAttributeSourceAdvisor,它通过父类TransactionAttributeSourcePointcut#matches完成匹配,如下:

TransactionAttributeSourcePointcut 查找@Transactional注解


下面是 TransactionAttributeSourcePointcut 进行匹配的源码:

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

@Override

public boolean matches(Method method, @Nullable Class<?> targetClass) {

if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {

return false;

}

//获取 BeanFactoryTransactionAttributeSourceAdvisor 中的AnnotationTransactionAttributeSource

TransactionAttributeSource tas = getTransactionAttributeSource();

//判断TransactionAttribute不为空,说明该targetClass的method是有事务注解的

return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);

}

这里getTransactionAttributeSource();方法由子类BeanFactoryTransactionAttributeSourceAdvisor 来实现,目的是获取TransactionAttributeSource 对象,然后调用tas.getTransactionAttribute获取TransactionAttribute,不为空说明方法是支持@Transational的。

tas.getTransactionAttribute 方法中会先通过类名和方法名构建一个key,从缓存中 attributeCache 获取TransactionAttribute,如果没有,就通过AnnotationTransactionAttributeSource#determineTransactionAttribute 去解析当前Method 的@Transactional封装成 TransactionAttribute,并装入缓存。源码如下;

org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute

public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {

if (method.getDeclaringClass() == Object.class) {

return null;

}

// First, see if we have a cached value.

//构建一个缓存key

Object cacheKey = getCacheKey(method, targetClass);

//从缓存中获取TransactionAttribute

TransactionAttribute cached = this.attributeCache.get(cacheKey);

if (cached != null) {

// Value will either be canonical value indicating there is no transaction attribute,

// or an actual transaction attribute.

if (cached == NULL_TRANSACTION_ATTRIBUTE) {

return null;

}

else {

//返回缓存中的TransactionAttribute

return cached;

}

}

else {

// We need to work it out.

//查找和解析method的事务注解,封装成TransactionAttribute

TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);

// Put it in the cache.

if (txAttr == null) {

this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);

}

else {

String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);

if (txAttr instanceof DefaultTransactionAttribute) {

((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);

}

if (logger.isDebugEnabled()) {

logger.debug(“Adding transactional method '” + methodIdentification + "’ with attribute: " + txAttr);

}

//把 TransactionAttribute 放入缓存attributeCache

this.attributeCache.put(cacheKey, txAttr);

}

return txAttr;

}

}

我们看一下 computeTransactionAttribute 方法的源码

protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {

// Don’t allow no-public methods as required.

总结

谈到面试,其实说白了就是刷题刷题刷题,天天作死的刷。。。。。

为了准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的

并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)

我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...

66个Java面试知识点

架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)

我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...

算法刷题(PDF)

我的美团offer凉凉了?开发工程师(Java岗)三面结束等通知...

n txAttr;

}

}

我们看一下 computeTransactionAttribute 方法的源码

protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {

// Don’t allow no-public methods as required.

总结

谈到面试,其实说白了就是刷题刷题刷题,天天作死的刷。。。。。

为了准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的

并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)

[外链图片转存中…(img-yV6YF6du-1714473717007)]

66个Java面试知识点

架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)

[外链图片转存中…(img-RR6R8n44-1714473717008)]

算法刷题(PDF)

[外链图片转存中…(img-X7koZAeN-1714473717008)]

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

  • 10
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值