spring 事务_spring事务初始化源码分析

前言

在上篇文章 Spring 事务使用详解 中详细介绍了 Spring 事务的使用过程,而今天就来看下 Spring 事务是如何来实现,比如 Spring 事务在初始化的时候做了什么,Spring 事务是如何进行事务的提交和回滚的;为了避免篇幅太长,所以分开两篇文章进行分析,这篇文章先来分析下 Spring 事务是如何初始化的,在初始化的时候做了什么。

注册 InfrastructureAdvisorAutoProxyCreator

我们知道,想要使用 Spring 事务,就得开启 Spring 的事务功能,如果是配置文件的方式,则需要在配置文件中配置 标签,那么分析 Spring 事务初始化就从解析该标签开始。

TxNamespaceHandler 类的 init方法中可以看到解析该标签的代码逻辑:

public class TxNamespaceHandler extends NamespaceHandlerSupport {    // .......@Overridepublic void init() {registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());}}

所以,当在解析 标签的时候,会使用 AnnotationDrivenBeanDefinitionParser 类的 parse方法来进行解析:

// AnnotationDrivenBeanDefinitionParser.javapublic BeanDefinition parse(Element element, ParserContext parserContext) {this.registerTransactionalEventListenerFactory(parserContext);String mode = element.getAttribute("mode");if ("aspectj".equals(mode)) {        // aspectj 模式this.registerTransactionAspect(element, parserContext);} else {        // proxy 模式 AnnotationDrivenBeanDefinitionParser.AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);}return null;}

接下来看下proxy模式,即默认模式的解析;使用的是它的内部类 AopAutoProxyConfigurerconfigureAutoProxyCreator方法进行解析:

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);    // ...............}

在该方法中,第一行就是进行注册 InfrastructureAdvisorAutoProxyCreator,还有其他的bean的注册,这里先不管;先来看下注册过程:

public static void registerAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {    // 注册BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));    // 处理proxy-target-class和 expose-proxy属性useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);    // ......}

这里和 Spring AOP 的处理流程是一样的,显示注册目标bean,再处理 proxy-target-classexpose-proxy 属性,可以参考 Spring AOP 注解方式源码解析 ,注册 AopConfigUtils.registerAutoProxyCreatorIfNecessary:

public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,Object source) {return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);}private static BeanDefinition registerOrEscalateApcAsRequired(Class> cls, BeanDefinitionRegistry registry,Object source) {    // 处理优先级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;}

关于该bean的作用下面分析,再 AopAutoProxyConfigurerconfigureAutoProxyCreator方法中除了注册该bean,还注册了三个bean,这三个bean用来支撑Spring的整个事务功能:

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {    // 注册 InfrastructureAdvisorAutoProxyCreatorAopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);// 事务AdvisorBeanNameString txAdvisorBeanName = "org.springframework.transaction.config.internalTransactionAdvisor";if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {    // 注册 AnnotationTransactionAttributeSourceObject eleSource = parserContext.extractSource(element);RootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");sourceDef.setSource(eleSource);sourceDef.setRole(2);String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);// 注册 TransactionInterceptorRootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);interceptorDef.setSource(eleSource);interceptorDef.setRole(2);AnnotationDrivenBeanDefinitionParser.registerTransactionManager(element, interceptorDef);interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);// 注册 BeanFactoryTransactionAttributeSourceAdvisorRootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);advisorDef.setSource(eleSource);advisorDef.setRole(2);// 并把上面注册的两个bean当作该bean的属性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);        // 注册其他的事件通知组件}}

这三个 bean 关系如下:

cef9a61fff9bacb36236bd8c7e2f7a65.png

InfrastructureAdvisorAutoProxyCreator

这个类是什么意思呢?它有什么用呢?按照类名来理解就是 基础的 Advisor 自动代理创建器,对于自定义的 Advisor,则不用它来创建,它的类图如下:

c86ae4b27d41e14cbfe6e23f21f8d05e.png

可以看到它实现了 BeanPostProcessor接口,而在前面分析 Spring 相关源码的时候知道,该接口是 Spring 提供了一个扩展接口,有两个方法:

public interface BeanPostProcessor {    // bean 初始化之前执行default Object postProcessBeforeInitialization(Object bean, String beanName){return bean;}    // bean 初始化之后执行default Object postProcessAfterInitialization(Object bean, String beanName) {return bean;}}

所以,当我们定义的一个 bean 初始化完成后,就会执行 postProcessAfterInitialization 方法,而 InfrastructureAdvisorAutoProxyCreator类实现了该方法:

public Object postProcessAfterInitialization(Object bean, String beanName) {if (bean != null) {        // 根据 beanClassName 和 beanName 创建一个keyObject cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.contains(cacheKey)) {            // 包装 beanreturn wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}// 包装beanprotected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {    // 已经处理过了,直接返回if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}    // 该 bean不需要增强,直接返回if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}    // 是否是Advice.class, Pointcut.class, Advisor.class, AopInfrastructureBean.class 这几个类,如果是    // 这几个类,或者该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;}// 创建代理protected Object createProxy(Class> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {    // ....ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);if (!proxyFactory.isProxyTargetClass()) {if (shouldProxyTargetClass(beanClass, beanName)) {            // CGLIB 代理proxyFactory.setProxyTargetClass(true);}else {            // JDK接口代理evaluateProxyInterfaces(beanClass, proxyFactory);}}    // 创建代理return proxyFactory.getProxy(getProxyClassLoader());}// 真正创建代理public Object getProxy(ClassLoader classLoader) {return createAopProxy().getProxy(classLoader);}protected final synchronized AopProxy createAopProxy() {    //.....return getAopProxyFactory().createAopProxy(this);}public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {    // 判断 CGLIB 代理和 JDK 代理的条件if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {Class> targetClass = config.getTargetClass();        // JDK 代理if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}        // CGLIB 代理return new ObjenesisCglibAopProxy(config);}else {        // JDK 代理return new JdkDynamicAopProxy(config);}}

上述的这段代码,当我们的 bean 初始化完成后,就会为该 bean 创建代理,创建代理的时候,根据配置条件创建 JDK 动态代理或者 CGLIB 代理

Spring 代理创建参考 Spring AOP 创建代理的源码解析

但是,是不是所有的 bean 都会创建代理呢,不是的,在包装 bean 的方法 wrapIfNecessary 中,会去查找该bean对应的增强,如果有相应的增强,则才会去创建代理,所有说在创建代理之前,会先去查找该 bean 对应的增强(拦截器),在 wrapIfNecessary 方法中有该代码:

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

对于 Spring 事务来说,该方法返回 specificInterceptors 不可能为空,所以才会走后面创建代理的逻辑。

接下来看下该方法的实现过程,即查询对应 class 或 method 的增强器。

查询对应 class 或 method 的增强器

getAdvicesAndAdvisorsForBean方法中,第一步,要找出符合条件的增强器,第二步,需要判断增强器是否符合要求。

protected Object[] getAdvicesAndAdvisorsForBean(Class> beanClass, String beanName,TargetSource targetSource) {    // 根据 className 和 beanName 找出符合条件的增强器List advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();}// 找出增强器protected List findEligibleAdvisors(Class> beanClass, String beanName) {    //查找增强器List candidateAdvisors = findCandidateAdvisors();    //判断增强器是否符合条件List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);    //.......return eligibleAdvisors;}

查找增强器 findCandidateAdvisors:

protected List findCandidateAdvisors() {return this.advisorRetrievalHelper.findAdvisorBeans();}public List findAdvisorBeans() {String[] advisorNames = this.cachedAdvisorBeanNames;if (advisorNames == null) {    // 获取所有 Advisor.class 类 // 在前面注册的 bean:BeanFactoryTransactionAttributeSourceAdvisor 也是一个 Advisor,// 所以,在这里该 bean 会被提取出来,后续一起植入代理advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);this.cachedAdvisorBeanNames = advisorNames;}List advisors = new ArrayList<>();for (String name : advisorNames) {   // 判断增强器bean是否符合条件,这里返回true    if (isEligibleBean(name)) {     if (this.beanFactory.isCurrentlyInCreation(name)) {//跳过正在创建的增强器    } else { advisors.add(this.beanFactory.getBean(name, Advisor.class));      }   }}return advisors;}

这里要说明一下,在前面注册的bean:BeanFactoryTransactionAttributeSourceAdvisor,它也是一个 Advisor,所以在获取所有的 Advisor.class 类的时候,也会把该 bean 提取出来;此外,该 bean 还拥有 AnnotationTransactionAttributeSource 和 TransactionInterceptor 这两个 bean,后面会一起被织入代理。

当查找到所有的增强后,需要判断哪些增强符合我们的目标 bean,对应方法 findAdvisorsThatCanApply:

public static List findAdvisorsThatCanApply(List candidateAdvisors, Class> clazz) {    // 用来存放符合条件的增强List eligibleAdvisors = new ArrayList<>();    // 处理引介增强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) {// 在处理引介增强时已经处理过了continue;}        // 普通的beanif (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}

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) {        /// pca=BeanFactoryTransactionAttributeSourceAdvisorPointcutAdvisor pca = (PointcutAdvisor) advisor;        //pca.getPointcut()=TransactionAttributeSourcePointcutreturn canApply(pca.getPointcut(), targetClass, hasIntroductions);}else {return true;}}

对于一个事务 bean 来说,该增强 Advisor 就是前面注册的 BeanFactoryTransactionAttributeSourceAdvisor,而该 bean 实现了 PointcutAdvisor 接口,所以会通过 第二个 if 判断;之后 通过 getPointcut 得到 TransactionAttributeSourcePointcut 对象继续调用 重载的 canApply 方法如下:

public static boolean canApply(Pointcut pc, Class> targetClass, boolean hasIntroductions) {// 获取方法匹配器    // 此时的匹配器是 TransactionAttributeSourcePointcutMethodMatcher methodMatcher = pc.getMethodMatcher();// 如果可以匹配所有方法,则不再循环方法进行判断if (methodMatcher == MethodMatcher.TRUE) {return true;}    // 存放目标类和目标类所有的接口Set> 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;}

到这里,只看到了根据方法去判断是否符合增强器,没有根据类来和接口判断,因为事务注解 Translation 可以放在类或接口上,对其下的所有public方法有用;其实,对类和接口的判断条件在是在 matcher 方法里面,调用的使用 TransactionAttributeSourcePointcut的 mathcer 方法:

public boolean matches(Method method, Class> targetClass) {// .....TransactionAttributeSource tas = getTransactionAttributeSource();return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);}

这里的 tas 就是 AnnotationTransactionAttributeSource,即在文章开头注册的那三个 bean 之一,它的 getTransactionAttribute 如下,去获取事务:

public TransactionAttribute getTransactionAttribute(Method method, Class> targetClass) {// 忽略 Object 的方法if (method.getDeclaringClass() == Object.class) {return null;}// 根据method和class来创建keyObject cacheKey = getCacheKey(method, targetClass);// 根据key查询事务,TransactionAttribute cached = this.attributeCache.get(cacheKey);if (cached != null) {   //...   // 已经判断过了   return cached;}else {   TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);   //....   return txAttr;}}

computeTransactionAttribute 方法如下:

protected TransactionAttribute computeTransactionAttribute(Method method, Class> targetClass) {// 不是public方法,则跳过if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {return null;}// 实现类的方法Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);// 首先在实现类的方法上查询注解,查询到,则直接返回TransactionAttribute txAttr = findTransactionAttribute(specificMethod);if (txAttr != null) {return txAttr;}// 如果在实现类对应方法上找不到注解,则在方法的实现类上查找注解,找到直接返回txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {return txAttr;}    // 存在接口if (specificMethod != method) {// 在接口方法上查找注解,找到直接返回txAttr = findTransactionAttribute(method);if (txAttr != null) {return txAttr;}// 如果在接口方法上找不到注解,则在接口上查找注解txAttr = findTransactionAttribute(method.getDeclaringClass());if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {return txAttr;}}return null;}

在上述的 computeTransactionAttribute 方法中,可以看到,去查找是一个事务方法,首先在实现类的方法上查找,找到直接返回,如果还找不到,则在实现类上查找注解;如果在实现类上找不到,再到接口上的方法里面去找,如果接口方法还找不到,则再接口上查找;所以,在这里可以看到,放在类或接口上事务注解可以作用于其下的所有 public 方法,且 方法上的事务注解要优先于类或接口上的注解,即如果再类,接口和方法上都加上事务注解,则会以方法上的注解为准,其次是 类,最后才是接口。

之后,就是去解析注解的属性,对应方法为:findTransactionAttribute,

protected TransactionAttribute findTransactionAttribute(Method method) {return determineTransactionAttribute(method);}protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {    // 事务注解解析器for (TransactionAnnotationParser annotationParser : this.annotationParsers) {TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);if (attr != null) {return attr;}}return null;}// 方法上获取 Transactional 注解public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {    // 在方法上获取 Transactional 注解AnnotationAttributes attributes =AnnotatedElementUtils.findMergedAnnotationAttributes(element, Transactional.class, false, false);if (attributes != null) {    // 解析 Transactional 注解属性return parseTransactionAnnotation(attributes);}else {return null;}}// 解析 Transactional 注解属性protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();Propagation propagation = attributes.getEnum("propagation");rbta.setPropagationBehavior(propagation.value());Isolation isolation = attributes.getEnum("isolation");rbta.setIsolationLevel(isolation.value());rbta.setTimeout(attributes.getNumber("timeout").intValue());rbta.setReadOnly(attributes.getBoolean("readOnly"));rbta.setQualifier(attributes.getString("value"));List rollbackRules = new ArrayList<>();for (Class> rbRule : attributes.getClassArray("rollbackFor")) {rollbackRules.add(new RollbackRuleAttribute(rbRule));}for (String rbRule : attributes.getStringArray("rollbackForClassName")) {rollbackRules.add(new RollbackRuleAttribute(rbRule));}for (Class> rbRule : attributes.getClassArray("noRollbackFor")) {rollbackRules.add(new NoRollbackRuleAttribute(rbRule));}for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {rollbackRules.add(new NoRollbackRuleAttribute(rbRule));}rbta.setRollbackRules(rollbackRules);return rbta;}

在这里就可以看到,事务注解 Transaction 的各种各样的属性了。

当然,到这里还没有完;到这里,可以从下往上看下所有的代码,当方法存在 Transaction 注解的时候,该方法 就会满足增强器 BeanFactoryTransactionAttributeSourceAdvisor ,之后就会为我们的目标bean 创建代理,并把 增强器BeanFactoryTransactionAttributeSourceAdvisor织入到代理中,进而来影响我们的业务逻辑。

总结

这篇文章主要介绍了 Spring 事务的初始化功能,在 Spring 加载的时候,会注册 InfrastructureAdvisorAutoProxyCreator bean,而该 bean 又实现了 BeanPostProcessor接口,所以当目标bean在初始化完成后,会执行 postProcessAfterInitialization 方法,在该方法中,会去遍历我们的目标 bean 中的方法,如果方法上有 Translaction 事务注解,则会为目标 bean 创建代理,并把 增强器BeanFactoryTransactionAttributeSourceAdvisor织入到代理中;当然,BeanFactoryTransactionAttributeSourceAdvisor该 bean 还拥有 AnnotationTransactionAttributeSource 和 TransactionInterceptor 这两个 bean,会一起被织入代理。

所以在 Spring 事务初始化的过程中,主要注册了四个 bean:

1. InfrastructureAdvisorAutoProxyCreator

2. BeanFactoryTransactionAttributeSourceAdvisor

3. AnnotationTransactionAttributeSource

4. TransactionInterceptor

InfrastructureAdvisorAutoProxyCreator主要是用来查找方法,类或者接口上的事务注解Translaction,如果存在注解,则为目标bean创建代理,并把其他的三个 bean 织入到代理中,而另外的三个 bean 主要是用来 执行目标方法,进行事务的提交和回滚。