Spring事务如何基于SpringAOP来实现事务代理?

通常我们要开启spring的事务我们需要加上@EnableTransactionManagement这个注解,那么肯定的这个注解的作用就是往容器里面去import了一个组件从而使得方法上面的@Transaction注解生效,而且spring事务的原理也是基于代理去实现事务回滚,事务隔离等功能的,那么既然是基于代理的原理,spring的事务与springAOP在实现这方面上有何异曲同工之处呢?

首先来看看@EnableTransactionManagement这个注解做了什么事

@Override
protected String[] selectImports(AdviceMode adviceMode) {
   switch (adviceMode) {
      case PROXY:
         return new String[] {AutoProxyRegistrar.class.getName(),
               ProxyTransactionManagementConfiguration.class.getName()};
      case ASPECTJ:
         return new String[] {determineTransactionAspectClass()};
      default:
         return null;
   }
}

这个注解往里面导入了一个TransactionManagementConfigurationSelector,最终这个selector往容器导入了两个组件,分别是AutoProxyRegistrar和ProxyTransactionManagementConfiguration

AutoProxyRegistrar

这个类又是一个ImportBeanDefinitionRegistrar组件,所以最终会调用registerBeanDefinitions这个方法,根据参数中的registry去向容器注册BeanDefinition,最终注册的逻辑:

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

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

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

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

   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;
   }

   RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
   beanDefinition.setSource(source);
   beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
   beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
   registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
   return beanDefinition;
}

上面的代码不必再过多解释,就是往容器中注册了一个InfrastructureAdvisorAutoProxyCreator这个类,接下来我们再来看下ProxyTransactionManagementConfiguration这个类

ProxyTransactionManagementConfiguration

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

   @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
      BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
      advisor.setTransactionAttributeSource(transactionAttributeSource());
      advisor.setAdvice(transactionInterceptor());
      if (this.enableTx != null) {
         advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
      }
      return advisor;
   }

   @Bean
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public TransactionAttributeSource transactionAttributeSource() {
      return new AnnotationTransactionAttributeSource();
   }

   @Bean
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public TransactionInterceptor transactionInterceptor() {
      TransactionInterceptor interceptor = new TransactionInterceptor();
      interceptor.setTransactionAttributeSource(transactionAttributeSource());
      if (this.txManager != null) {
         interceptor.setTransactionManager(this.txManager);
      }
      return interceptor;
   }

}

这个类就是 一个配置类,里面配置3个需要往容器中去注册的Bean,分别是BeanFactoryTransactionAttributeSourceAdvisor,TransactionAttributeSource,TransactionInterceptor并且需要注意的是这三个bean都使用@Role注解声明为ROLE_INFRASTRUCTURE,这个在后面的代码中会用到。上面我们先总结下@EnableTransactionManagement注解最终做了就是往spring容器中导入了4个关键组件,分别是InfrastructureAdvisorAutoProxyCreator,BeanFactoryTransactionAttributeSourceAdvisor,TransactionAttributeSource,TransactionInterceptor

InfrastructureAdvisorAutoProxyCreator

先看下这个类的继承关系图

 能够看到这个类最终也是继承于AbstractAutoProxyCreator,在前面SpringAOP的自动代理就说过这个类,这个类实现了BeanPostProcessor下面的两个子接口,所以在当bean在实例化之前和初始化之后都会被这个类所拦截,这里细节就不再多说,我们直接看拦截的方法

实例化之前org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
   Object cacheKey = getCacheKey(beanClass, beanName);

   if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
      if (this.advisedBeans.containsKey(cacheKey)) {
         return null;
      }
      if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
         this.advisedBeans.put(cacheKey, Boolean.FALSE);
         return null;
      }
   }

   // Create proxy here if we have a custom TargetSource.
   // Suppresses unnecessary default instantiation of the target bean:
   // The TargetSource will handle target instances in a custom fashion.
   TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
   if (targetSource != null) {
      if (StringUtils.hasLength(beanName)) {
         this.targetSourcedBeans.add(beanName);
      }
      Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
      Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }

   return null;
}

这个方法在SpringAOP中主要就是去解析我们的aspect切面类得到解析后的advisor并缓存起来,而spring事务在这里却没有做什么事情。初始化之后就要来到bean的初始化之后的后置处理了:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
   if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
      return bean;
   }
   if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
      return bean;
   }
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
   }

   // Create proxy if we have advice.
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
   if (specificInterceptors != DO_NOT_PROXY) {
      this.advisedBeans.put(cacheKey, Boolean.TRUE);
      Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
   }

   this.advisedBeans.put(cacheKey, Boolean.FALSE);
   return bean;
}

和SpringAOP套路一样,都是在bean初始化的后置方法里面去生成代理对象,在生成代理对象之前会先寻找适合该bean使用的advisor,那么重点来看getAdvicesAndAdvisorsForBean这个方法

org.springframework.aop.framework.autoproxy.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();
}

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
   // 寻找候选的advisor
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
   // 从寻找到的候选的advisor中去找到适合该bean的advisor
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}

org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findCandidateAdvisors

protected List<Advisor> findCandidateAdvisors() {
   Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
   // 调用了AbstractAdvisorAutoProxyCreator中寻找候选advisor辅助类
   return this.advisorRetrievalHelper.findAdvisorBeans();
}

这个辅助类重写了它父类的isEligibleBean方法,而isEligibleBean方法是判断advisor是否能够成为候选的条件判断方法

private class BeanFactoryAdvisorRetrievalHelperAdapter extends BeanFactoryAdvisorRetrievalHelper {

   public BeanFactoryAdvisorRetrievalHelperAdapter(ConfigurableListableBeanFactory beanFactory) {
      super(beanFactory);
   }

   @Override
   protected boolean isEligibleBean(String beanName) {
      return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName);
   }
}

根据上面我们的分析,上面的方法我们一直所执行的对象都是InfrastructureAdvisorAutoProxyCreator,只不过都是这个类的父类的方法,而在这里的isEligibleBean方法,里面调用的AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName)这句代码刚好就被InfrastructureAdvisorAutoProxyCreator所重写了

@Override
protected boolean isEligibleAdvisorBean(String beanName) {
   return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) &&
         this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
}

而在InfrastructureAdvisorAutoProxyCreator中重写判断advisor是否是候选的advisor的条件就是这个advisor的role等于BeanDefinition.ROLE_INFRASTRUCTURE,这个值是不是有点眼熟?没错,就是上面叫大家去注意的地方,回到ProxyTransactionManagementConfiguration这个类,这个类在spring容器进行bean注册的时候就往容器中放进了三个bean,而这三个bean的role都等于BeanDefinition.ROLE_INFRASTRUCTURE

@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
   BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
   advisor.setTransactionAttributeSource(transactionAttributeSource());
   advisor.setAdvice(transactionInterceptor());
   if (this.enableTx != null) {
      advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
   }
   return advisor;
}

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
   return new AnnotationTransactionAttributeSource();
}

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
   TransactionInterceptor interceptor = new TransactionInterceptor();
   interceptor.setTransactionAttributeSource(transactionAttributeSource());
   if (this.txManager != null) {
      interceptor.setTransactionManager(this.txManager);
   }
   return interceptor;
}

在这里就可以说下这三个bean的作用了,第一个bean是一个advisor,在寻找候选的advisor方法的时候会从容器中getBean可以得到,然后又符合了role等于BeanDefinition.ROLE_INFRASTRUCTURE的条件,所以此时最终候选的advisor只有这个advisor,第二个bean能够作用于advisor的pointcut处理,是用来配合处理判断目标bean是否符合这个advisor的,判断逻辑就是判断该bean的方法或者类上面是否有@Transactional注解,如果有就说明这个advisor适用于这个bean,而第三个就是我们的事务拦截器了,代理对象增强逻辑的地方,会处理有关spring事务的所有事情

总结

关于advisor中的pointcut的细节逻辑是怎样的,以及之后的事务增强的处理就不细说了,我们这里主要是去学习到了整个spring事务在创建代理以及寻找advisor,MethodInteceptor的过程与SpringAOP的相似之处,SpringAOP是会在bean实例化之前的前置处理会先去解析aspect切面并且把解析出来的advisor缓存起来,而spring事务在这一步基本上没做什么处理,然后在bean初始化的后置处理SpringAOP和spring事务都会去创建代理对象,但是两者在寻找advisor的逻辑上就有些不同,SpringAOP是会找出spring容器中所有的advisor(包括了解析aspect切面的advisor),而spring事务是找role等于BeanDefinition.ROLE_INFRASTRUCTURE的advisor,之后两者在判断适用于bean的advisor的pointcut的逻辑也是各自的不同,最后在代理对象执行方法的时候,如果单独只开启了spring事务那么此时的拦截链是只会有一个,就是上面注册的TransactionInterceptor这个bean

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值