spring bean 作用域原理(Spring框架系列之bean的生命周期底层原理之数据库事务整合)
spring bean 作用域原理(Spring框架系列之bean的生命周期底层原理之数据库事务整合)另外咱们来回顾下,在Spring关于Bean的整个生命周期处理过程中,AOP处理发生的时间点以及处理的方式是怎样的呢?这个很重要,因为咱们不可能去修改Spring原有的代码,而只能利用Spring为咱们提供的扩展点来实现数据库的事务处理。而Spring针对事务的处理其实就是在不改动原有代码的情况下,如何添加上述第一步和第三步两个动作,要如何做到呢?其实我们考虑下整个需求,其实就是对原有的数据库操作做了增强的处理,而这个增强处理对于所有想要有事务处理的类来说都是相同的,而这其实就是Spring的AOP的典型应用场景,很明显这里咱们可以Spring的AOP。1.获取数据库连接,设置自动提交的值为false;2.执行SQL语句;3.如果SQL执行成功则执行提交,否则执行回滚操作。
Spring可以说是Java界使用最广泛的框架,没有之一,所以前面咱们花了16章的篇幅,把Spring框架的底层大概分析了一遍。到了这里,笔者觉得是时候开始讲下Spring对于数据库事务的处理机制了,其实只要老铁们把Spring的底层原理整明白了,完全可以自己去分析数据库事务的处理机制。
那么笔者就和大家一起来探讨下,如果是咱们自己来设计Spring对数据库的事务处理机制,咱们应该如何来思考!
要设计数据库的事务处理机制,那首先得了解在使用JDBC执行SQL的情况下,咱们是怎么处理事务的呢?
大概分为几个步骤:
1.获取数据库连接,设置自动提交的值为false;
2.执行SQL语句;
3.如果SQL执行成功则执行提交,否则执行回滚操作。
而Spring针对事务的处理其实就是在不改动原有代码的情况下,如何添加上述第一步和第三步两个动作,要如何做到呢?其实我们考虑下整个需求,其实就是对原有的数据库操作做了增强的处理,而这个增强处理对于所有想要有事务处理的类来说都是相同的,而这其实就是Spring的AOP的典型应用场景,很明显这里咱们可以Spring的AOP。
另外咱们来回顾下,在Spring关于Bean的整个生命周期处理过程中,AOP处理发生的时间点以及处理的方式是怎样的呢?这个很重要,因为咱们不可能去修改Spring原有的代码,而只能利用Spring为咱们提供的扩展点来实现数据库的事务处理。
正常情况下,Spring的AOP处理是发生在初始化后,而非正常情况下,也就是出现循环依赖的情况下,Spring会提前进行AOP,当然,不管是非正常情况或是正常情况,AOP的底层实现逻辑是一样的。
大家想起来这个底层逻辑了嘛?这里Spring会执行所有后置处理器的postProcessAfterInitialization方法,所以如果是咱们自己去实现,则是可以自己实现后置处理的逻辑,当然这里Spring给我们提供了专门用于AOP的抽象类:AbstractAutoProxyCreator,咱们继承这个类,实现指定的逻辑,当然这个指定的逻辑是啥,我们后面看Spring是怎么实现的。
我想这里的逻辑大概过程应该包括:将满足一定条件的类,生成代理对象,当操作这个代理对象的时候,所有的方法调用首先都会经过判断,该方法到底需不需要增强处理,如果需要,则会经过增强处理,也就是设置"自动提交值为false",当方法调用完成后,也会执行提交或回滚的增强逻辑,当然这些增强的逻辑有很多细节需要处理,比如如何跨事务处理等。
以上是我们的大概想法,那接下来,咱们看看Spring是如何处理数据库事务的,笔者将Spring的事务处理机制归结为几个大的步骤:注册后置处理器、生成代理对象、方法增强处理,下面详细描述每个步骤:
一、注册后置处理器
Spring通过增加注解EnableTransactionManagement来开启数据库事务,这个是数据库事务的入口,一切的起源就在这个注解类上:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement{......}
    
再看TransactionManagementConfigurationSelector:
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
   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;
      }
   }
}
    
好,到这里,我们可以看到,Spring将会往Bean工厂中添加AutoProxyRegistrar和ProxyTransactionManagementConfiguration的Bean实例。
来继续看:
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
   ......
   public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata  BeanDefinitionRegistry registry) {
      boolean candidateFound = false;
      Set<String> 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);
               if ((Boolean) proxyTargetClass) {
                  AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                  return;
               }
            }
         }
      }
     ......
   }
}
    
其中AnnotationConfigUtils.attributesFor(importingClassMetadata annType)这个方法,是获取EnableTransactionManagement注解的属性值,而AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)方法,则是注册一个InfrastructureAdvisorAutoProxyCreator类型的Bean,这个Bean的注册名称为:org.springframework.aop.config.internalAutoProxyCreator。
而ProxyTransactionManagementConfiguration则是一个配置类,其中定义了很多重要的Bean实例,其中一个实例类型:BeanFactoryTransactionAttributeSourceAdvisor,它是PointcutAdvisor的实现类,这个类表示啥意思呢?它是切点和代理逻辑(也就是Advice)的封装类,是生成AOP代理对象的核心参数,表示在调用代理对象时,需要对哪些方法进行增强,以及增强的代理逻辑:
@Configuration(proxyBeanMethods = false)
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.<Integer>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;
   }
}
    
可以看出,切点是AnnotationTransactionAttributeSource对象,而TransactionInterceptor则是代理逻辑对象。
可以想想,这里所有代理对象的切点类都是AnnotationTransactionAttributeSource对象,代理逻辑都是TransactionInterceptor,代理逻辑是一个对象可以理解,因为都设置autocommit、提交事务、回滚事务都是相同的。而切点是同一个,则表明在这个AnnotationTransactionAttributeSource有很多的处理逻辑是针对某个具体的原始对象进行的,而事实上,也确实是这样。
二、生成代理对象
如上面所说,Spring向Bean工厂中添加了InfrastructureAdvisorAutoProxyCreator类型的对象,它的继承关系结构如下:

它是BeanPostProcessor的实现类,所以初始化完成后,会进入该类的postProcessAfterInitialization方法(这个方法是在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;
   }
 
   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;
}
    
其中getAdvicesAndAdvisorsForBean方法是关键,这里就是用来获取咱们上面说的BeanFactoryTransactionAttributeSourceAdvisor这个Advisor,我们直到,所有的Bean都会进入这个后置处理器的postProcessAfterInitialization方法,所以不可能是所有的Bean都会返回这个Advisor,一定是满足某些条件的Bean才会返回这个Advisor,那问题来了,这个条件是啥呢?
我们来一步步跟踪下就清楚了:
上述AbstractAutoProxyCreator会调用getAdvicesAndAdvisorsForBean获取Bean支持的所有Advisor,进入到findEligibleAdvisors方法中,在findEligibleAdvisors方法中,List<Advisor> candidateAdvisors = findCandidateAdvisors()会得到所有的Advisor,这里可以获取到我们上面定义的BeanFactoryTransactionAttributeSourceAdvisor,然后调用findAdvisorsThatCanApply方法进行过滤,判断满足条件的Advisor:
protected Object[] getAdvicesAndAdvisorsForBean(
      Class<?> beanClass  String beanName  @Nullable TargetSource targetSource) {
   //关键点入口
   List<Advisor> advisors = findEligibleAdvisors(beanClass  beanName);
   if (advisors.isEmpty()) {
      return DO_NOT_PROXY;
   }
   return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass  String beanName) {
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
    //关键点入口
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors  beanClass  beanName);
		......
	}
    
protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors  Class<?> beanClass  String beanName) {
		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try { 
      //关键点入口
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors  beanClass);
		}finally {
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}
    
public abstract class AopUtils{
  ......
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors  Class<?> clazz) {
   ......
   boolean hasIntroductions = !eligibleAdvisors.isEmpty();
   for (Advisor candidate : candidateAdvisors) {
      if (candidate instanceof IntroductionAdvisor) {
         continue;
      } 
     //关键点入口
      if (canApply(candidate  clazz  hasIntroductions)) {
         eligibleAdvisors.add(candidate);
      }
   }
   return eligibleAdvisors;
}
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 { 
			return true;
		}
	}
 
	public static boolean canApply(Pointcut pc  Class<?> targetClass  boolean hasIntroductions) {
		Assert.notNull(pc  "Pointcut must not be null");
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}
		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) { 
			return true;
		}
		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}
		Set<Class<?>> classes = new LinkedHashSet<>();
		if (!Proxy.isProxyClass(targetClass)) {
			classes.add(ClassUtils.getUserClass(targetClass));
		}
		classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
 
		for (Class<?> clazz : classes) {
			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;
	}
    
哪些是满足条件的Advisor呢?这个逻辑是由AopUtils来进行处理,而最终的判断是methodMatcher.matches来进行判断,这个methodMatcher是个啥?它是BeanFactoryTransactionAttributeSourceAdvisor对象的TransactionAttributeSourcePointcut属性值,表示切点,它的matches方法:
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
   public boolean matches(Method method  Class<?> targetClass) {
      TransactionAttributeSource tas = getTransactionAttributeSource();
      //关键点入口
      return (tas == null || tas.getTransactionAttribute(method  targetClass) != null);
   }
  ......
}
    
可以看到调用了TransactionAttributeSource类的TransactionAttributeSource方法,这里大家应该直到TransactionAttributeSource这个类对象是在哪里注入到Spring中的吧?对,它就是AnnotationTransactionAttributeSource对象。

从上面类的继承关系图上可以看到,最终会进入到AbstractFallbackTransactionAttributeSource的getTransactionAttribute方法
public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {
  public TransactionAttribute getTransactionAttribute(Method method  @Nullable Class<?> targetClass) {
     if (method.getDeclaringClass() == Object.class) {
        return null;
     }
     Object cacheKey = getCacheKey(method  targetClass);
     TransactionAttribute cached = this.attributeCache.get(cacheKey);
     if (cached != null) {
        if (cached == NULL_TRANSACTION_ATTRIBUTE) {
           return null;
        }
        else {
           return cached;
        }
     }  else {
        //关键点入口
        TransactionAttribute txAttr = computeTransactionAttribute(method  targetClass); 
        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.isTraceEnabled()) {
              logger.trace("Adding transactional method '"   methodIdentification   "' with attribute: "   txAttr);
           }
           this.attributeCache.put(cacheKey  txAttr);
        }
        return txAttr;
     }
  }
}
    
而上述方法computeTransactionAttribute最终会调用SpringTransactionAnnotationParser的parseTransactionAnnotation来返回TransactionAttribute对象:
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser  Serializable {
  public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
     AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
           element  Transactional.class  false  false);
     if (attributes != null) {
        return parseTransactionAnnotation(attributes);
     }     else {
        return null;
     }
  }
}
    
上面如果被代理类类或方法上存在Transactional注解,则返回TransactionAttribute对象,否则返回null,这说明什么呢?说明只有被代理的类或方法上存在Transactional注解,才会返回BeanFactoryTransactionAttributeSourceAdvisor这个类型的Advisor对象,才会生成代理对象。
三、方法增强处理
这块涉及到具体的事务处理机制,咱们放到下一章节“Spring框架系列之bean的生命周期底层原理之事务处理机制?”详细分析。





