• spring 事务源码阅读


    开启事务

    使用@EnableTransactionManagement注解开启事务

    该注解会引入TransactionManagementConfigurationSelector类,然后该类导入两个类AutoProxyRegistrar和ProxyTransactionManagementConfiguration。

    1、添加bean后置处理器

    AutoProxyRegistrar类的作用是注册InfrastructureAdvisorAutoProxyCreator类,InfrastructureAdvisorAutoProxyCreator是Spring中实现AOP代理的关键组件,它会扫描所有的Advisor(通知器),并将其与BeanFactory中的Bean进行匹配,以决定是否需要为该Bean创建AOP代理。

    InfrastructureAdvisorAutoProxyCreator 继承AbstractAdvisorAutoProxyCreator 继承AbstractAutoProxyCreator,实现SmartInstantiationAwareBeanPostProcessor和BeanFactoryAware接口。

    是一个bean后置处理器

    public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
       @Nullable
       private ConfigurableListableBeanFactory beanFactory;
       @Override
       protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
          super.initBeanFactory(beanFactory);
          this.beanFactory = beanFactory;
       }
       @Override
       protected boolean isEligibleAdvisorBean(String beanName) {
          return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) &&
                this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
       }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    代理的创建在上一篇AOP源码阅读中有说过就是在后置处理器的after方法寻找合适的advisor进行创建代理。上面的源码看到InfrastructureAdvisorAutoProxyCreator只是重写了initBeanFactory方法用来获取beanfacotry和isEligibleAdvisorBean方法用来判断是否是合适的bean。

    2、引入Advisor

    TransactionManagementConfigurationSelector引入的另一个类是ProxyTransactionManagementConfiguration,该类代码也不多,如下

    @Configuration(proxyBeanMethods = false)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    
       @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) {
             advisor.setOrder(this.enableTx.getNumber("order"));
          }
          return advisor;
       }
    
       @Bean
       @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
       public TransactionAttributeSource transactionAttributeSource() {
          return new AnnotationTransactionAttributeSource();
       }
    
       @Bean
       @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
       public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
          TransactionInterceptor interceptor = new TransactionInterceptor();
          interceptor.setTransactionAttributeSource(transactionAttributeSource);
          if (this.txManager != null) {
             interceptor.setTransactionManager(this.txManager);
          }
          return interceptor;
       }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    ProxyTransactionManagementConfiguration类主要引入BeanFactoryTransactionAttributeSourceAdvisor通知类。并为其TransactionAttributeSource和TransactionInterceptor两个属性赋值。该类实现了Advisor接口,是一个PointcutAdvisor类型的Advisor,用来匹配@Transaction注解。具体如何匹配下面结合源码说。

    代理创建

    1、获取所有Advisor

    在AbstractAutoProxyCreator的后置出来器afater方法里还是会调用wrapIfNecessary(bean, beanName, cacheKey)来判断当前bean是否需要包装代理。然后会调用getAdvicesAndAdvisorsForBean(bean.getClass(), beanName)方法尝试获取适用于该bean的advice。这个方法在AbstractAdvisorAutoProxyCreator 中实现

    AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean

    protected Object[] getAdvicesAndAdvisorsForBean(
          Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
       //获取符合条件的advisor
       List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
       if (advisors.isEmpty()) {
          return DO_NOT_PROXY;
       }
       return advisors.toArray();
    }
    
    	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
            //获取候选的所有advisor
    		List<Advisor> candidateAdvisors = findCandidateAdvisors();
          //获取适用于当前bean的advisor
    		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    		extendAdvisors(eligibleAdvisors);
    		if (!eligibleAdvisors.isEmpty()) {
    			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    		}
    		return eligibleAdvisors;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    findCandidateAdvisors()方法还是在该类中实现,使用了一个BeanFactoryAdvisorRetrievalHelper工具类进行获取Advisor

    AbstractAdvisorAutoProxyCreator#findCandidateAdvisors

    protected List<Advisor> findCandidateAdvisors() {
         return this.advisorRetrievalHelper.findAdvisorBeans();
    }
    
    • 1
    • 2
    • 3

    BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans

    public List<Advisor> findAdvisorBeans() {
       String[] advisorNames = this.cachedAdvisorBeanNames;
       if (advisorNames == null) {
          //从beanfacotry总获取所有的Advisor
          advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                this.beanFactory, Advisor.class, true, false);
          this.cachedAdvisorBeanNames = advisorNames;
       }
       if (advisorNames.length == 0) {
          return new ArrayList<>();
       }
    
       List<Advisor> advisors = new ArrayList<>();
       for (String name : advisorNames) {
          if (isEligibleBean(name)) {//调用isEligibleBean判断bean是否满足基本条件
             advisors.add(this.beanFactory.getBean(name, Advisor.class));
          }
       }
       return advisors;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    这里看到Advisor的获取是直接从beanFacotry中查找Advisor.class类型的beanDef,这样就能找到我们最开始通过import导入的BeanFactoryTransactionAttributeSourceAdvisor。这和上一篇说的AOP的Aspect方式有一些区别(扫描所有的bean,反射解析@Aspect注解)。

    2、寻找匹配的Advisor

    找到所有的Advisor后下一步就是逐个判断是否适用于当前bean

    protected List<Advisor> findAdvisorsThatCanApply(
          List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    
       ProxyCreationContext.setCurrentProxiedBeanName(beanName);
       try {
          return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
       }
       finally {
          ProxyCreationContext.setCurrentProxiedBeanName(null);
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    AopUtils#findAdvisorsThatCanApply

    public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
       if (candidateAdvisors.isEmpty()) {
          return candidateAdvisors;
       }
       List<Advisor> eligibleAdvisors = new ArrayList<>();
       //这里不是IntroductionAdvisor类型的不会进入循环
       for (Advisor candidate : candidateAdvisors) {
          if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
             eligibleAdvisors.add(candidate);
          }
       }
       boolean hasIntroductions = !eligibleAdvisors.isEmpty();
       for (Advisor candidate : candidateAdvisors) {
          if (candidate instanceof IntroductionAdvisor) {
             // already processed
             continue;
          }
          //进入canApply方法判断
          if (canApply(candidate, clazz, hasIntroductions)) {
             eligibleAdvisors.add(candidate);
          }
       }
       return eligibleAdvisors;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    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 pca = (PointcutAdvisor) advisor;
          return canApply(pca.getPointcut(), targetClass, hasIntroductions);
       }
       else {
          // It doesn't have a pointcut so we assume it applies.
          return true;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    最开始说过我们引入的advisor是一个PointcutAdvisor类型。所以会进入第二个if分支。拿出pointcut进行匹配。这里的advisor是BeanFactoryTransactionAttributeSourceAdvisor实例,器pointcut是TransactionAttributeSourcePointcut类型实例。下一个重载canApply方法主要匹配逻辑是下面代码

    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
       //...
       //这里返回的matcher还是TransactionAttributeSourcePointcut本身
       MethodMatcher methodMatcher = pc.getMethodMatcher();
       for (Class<?> clazz : classes) {
         //拿出class所有方法与matcher进行匹配
          Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
          for (Method method : methods) {
             if (introductionAwareMethodMatcher != null ?
                   introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                   methodMatcher.matches(method, targetClass)) {
                return true;
             }
          }
       }
    
       return false;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    主要的匹配逻辑是methodMatcher.matches,也就是

    TransactionAttributeSourcePointcut#matches

    public boolean matches(Method method, Class<?> targetClass) {
       //获取TransactionAttributeSource,这是最开始在引入Advisor设置的
       TransactionAttributeSource tas = getTransactionAttributeSource();
       return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这里TransactionAttributeSource是最开始引入由ProxyTransactionManagementConfiguration类内部设置的,其实例类型是AnnotationTransactionAttributeSource ,该类继承 AbstractFallbackTransactionAttributeSource。getTransactionAttribute()方法在其父类中

    AbstractFallbackTransactionAttributeSource#getTransactionAttribute

    public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
       if (method.getDeclaringClass() == Object.class) {//Object类方法跳过
          return null;
       }
    
       // First, see if we have a cached value.
       Object cacheKey = getCacheKey(method, targetClass);
       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 {
             return cached;
          }
       }
       else {
          // 解析当前方法事务属性
          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 dta = (DefaultTransactionAttribute) txAttr;
                dta.setDescriptor(methodIdentification);
                dta.resolveAttributeStrings(this.embeddedValueResolver);
             }
    
             this.attributeCache.put(cacheKey, txAttr);
          }
          return txAttr;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    解析实际方法是computeTransactionAttribute()

    protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
       //step1 判断方法必须是public方法
       if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
          return null;
       }
    
       // The method may be on an interface, but we need attributes from the target class.
       // If the target class is null, the method will be unchanged.
       Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
    
       //step2 解析方法事务属性
       TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
       if (txAttr != null) {
          return txAttr;
       }
    
       // Second try is the transaction attribute on the target class.
       txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
       if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
          return txAttr;
       }
    
       if (specificMethod != method) {
          // Fallback is to look at the original method.
          txAttr = findTransactionAttribute(method);
          if (txAttr != null) {
             return txAttr;
          }
          // Last fallback is the class of the original method.
          txAttr = findTransactionAttribute(method.getDeclaringClass());
          if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
             return txAttr;
          }
       }
    
       return null;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    step2处findTransactionAttribute()方法解析事务属性,该方法是AnnotationTransactionAttributeSource类实现,其调用determineTransactionAttribute(method)方法。

    AnnotationTransactionAttributeSource#determineTransactionAttribute

    protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
       for (TransactionAnnotationParser parser : this.annotationParsers) {
          TransactionAttribute attr = parser.parseTransactionAnnotation(element);
          if (attr != null) {
             return attr;
          }
       }
       return null;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这里拿出所有的annotationParsers进行解析方法是否定义事务。annotationParsers是在AnnotationTransactionAttributeSource的构造方法初始化,这里有两个SpringTransactionAnnotationParser和JtaTransactionAnnotationParser。我们主要看SpringTransactionAnnotationParser。

    SpringTransactionAnnotationParser#parseTransactionAnnotation

    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
       AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
             element, Transactional.class, false, false);
       if (attributes != null) {
          return parseTransactionAnnotation(attributes);
       }
       else {
          return null;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    终于看到熟悉的Transactional注解了,也不往方法里面看了。这里就是解析@Transactional注解配置的事务属性。

    3、事务管理

    代理创建和AOP过程一致,这里还是以JDK代理类为例。代理对象是JdkDynamicAopProxy。原方法的执行会首先进入JdkDynamicAopProxy.invoke方法。

    这里还是从invoke的获取拦截器链开始

    List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

    最后会调到

    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
       List<MethodInterceptor> interceptors = new ArrayList<>(3);
       Advice advice = advisor.getAdvice();
       if (advice instanceof MethodInterceptor) {//会走这里
          interceptors.add((MethodInterceptor) advice);
       }
       for (AdvisorAdapter adapter : this.adapters) {//这是Aspect的情况
          if (adapter.supportsAdvice(advice)) {
             interceptors.add(adapter.getInterceptor(advisor));
          }
       }
       if (interceptors.isEmpty()) {
          throw new UnknownAdviceTypeException(advisor.getAdvice());
       }
       return interceptors.toArray(new MethodInterceptor[0]);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    这里要回到开始ProxyTransactionManagementConfiguration引入Advisor引入的地方

    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
          TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
    
       BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
       advisor.setTransactionAttributeSource(transactionAttributeSource);
       //设置的advisor是TransactionInterceptor类型
       advisor.setAdvice(transactionInterceptor);
       if (this.enableTx != null) {
          advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
       }
       return advisor;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    所以最后会调用TransactionInterceptor的invoke方法

    TransactionInterceptor#invoke

    public Object invoke(MethodInvocation invocation) throws Throwable {
       // Work out the target class: may be {@code null}.
       // The TransactionAttributeSource should be passed the target class
       // as well as the method, which may be from an interface.
       Class targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
    
       // Adapt to TransactionAspectSupport's invokeWithinTransaction...
       return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
          @Override
          @Nullable
          public Object proceedWithInvocation() throws Throwable {
             return invocation.proceed();
          }
          @Override
          public Object getTarget() {
             return invocation.getThis();
          }
          @Override
          public Object[] getArguments() {
             return invocation.getArguments();
          }
       });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    最后事务的控制在invokeWithinTransaction方法完成。

    总结

    开启事务为我们引入了两个重要的

    1、BeanFactoryTransactionAttributeSourceAdvisor事务Advisor。设置两个属性TransactionInterceptor用来代理管理事务,TransactionAttributeSource用来匹配事务方法。

    1、InfrastructureAdvisorAutoProxyCreator是bean后置处理器,用来判断当前bean是否需要代理。会拿出第一步引入的事务Advisor,与当前bean的所有方法进行匹配看是否有@Transaction注解。有就创建代理,最后使用BeanFactoryTransactionAttributeSourceAdvisor中设置的TransactionInterceptor拦截器进行事务管理。

    整理流程
    在这里插入图片描述

  • 相关阅读:
    动手实践:从栈帧看字节码是如何在 JVM 中进行流转的
    Matlab2022b软件如何切换中/英文界面?
    Mysql系列二:Mysql里的锁
    SpringBoot读取Resource下文件的几种方式读取jar里的excel,文件损坏
    swift指针&内存管理-引用
    【OpenCV】 - 图像分割之分水岭算法,watershed()函数的输出,对marker和image的改变
    [附源码]计算机毕业设计springboot招聘系统
    iTOP-RK3588开发板rknn_multiple_input_demo 体验
    字符串数数——考虑循环节:1108T3
    【SpringBoot从入门到精通】第一章 Spring与SpringBoot
  • 原文地址:https://blog.csdn.net/sinat_16493273/article/details/133644343