springboot事務(wù)管理源碼分析--1.啟動分析

本文基于springboot(1.5以上)的事務(wù)管理的開篇,主要關(guān)于Transaction注解的生效過程

Transaction注解怎么生效

springboot開啟事務(wù)管理需要在啟動類加上@EnableTransactionManagement,EnableTransactionManagement使用@Import導(dǎo)入TransactionManagementConfigurationSelector類,TransactionManagementConfigurationSelector實(shí)現(xiàn)了ImportSelector接口

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

默認(rèn)情況下是proxy 模式,會導(dǎo)入AutoProxyRegistrar(將InfrastructureAdvisorAutoProxyCreator納入spring管理,但是后續(xù)會被高優(yōu)先級的AnnotationAwareAspectJAutoProxyCreator替代)和ProxyTransactionManagementConfiguration。

1.先分析AutoProxyRegistrar

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean candidateFound = false;
        Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
        for (String annoType : annoTypes) {
            AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
            if (candidate == null) {
                continue;
            }
            // springboot中如果在main函數(shù)所在的Application類中加了EnableTransactionManagement注解
            // 下面這個(gè)判斷就會成立,默認(rèn)情況下mode是proxy,就會使用AopConfigUtils
            // 將InfrastructureAdvisorAutoProxyCreator加入spring容器
            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;
                    }
                }
            }
        }
    }

AutoProxyRegistrar是一個(gè)實(shí)現(xiàn)了ImportBeanDefinitionRegistrar接口的類, AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)會將InfrastructureAdvisorAutoProxyCreator加入了spring管理,但是真正用來創(chuàng)建代理的是AnnotationAwareAspectJAutoProxyCreator類,看下面這張繼承關(guān)系圖,兩者都繼承了AbstractAdvisorAutoProxyCreator,主要功能是類似的,那么AnnotationAwareAspectJAutoProxyCreator又是什么時(shí)候引入spring容器的呢?

Screenshot from 2019-01-22 10-25-46.png

這里就要涉及springboot是怎么實(shí)現(xiàn)自動配置的了。@SpringBootApplication會引入@EnableAutoConfiguration,這個(gè)注解會使用@Import導(dǎo)入 EnableAutoConfigurationImportSelector,此類的父類AutoConfigurationImportSelector實(shí)現(xiàn)了ImportSelector,在selectImports方法中使用AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader)導(dǎo)入META-INF/spring-autoconfigure-metadata.properties,導(dǎo)入@EnableAspectJAutoProxy,而@EnableAspectJAutoProxy又使用@Import導(dǎo)入了AspectJAutoProxyRegistrar,在這個(gè)類的selectImports會注冊上AnnotationAwareAspectJAutoProxyCreator這個(gè)Bean,也就是說其實(shí)只要是springboot項(xiàng)目都會導(dǎo)入這個(gè)Bean,而由于在AopConfigUtils將AnnotationAwareAspectJAutoProxyCreator和InfrastructureAdvisorAutoProxyCreator做了排序,如果存在AnnotationAwareAspectJAutoProxyCreator,那么InfrastructureAdvisorAutoProxyCreator就不會生效。

那什么時(shí)候會為加了Transaction注解的方法或者類加上事務(wù)管理功能呢?

2.分析AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator實(shí)現(xiàn)了AbstractAutoProxyCreator抽象類,AbstractAutoProxyCreator又實(shí)現(xiàn)了BeanPostProcessor接口,熟悉spring IOC的都知道在每個(gè)Bean執(zhí)行完初始化方法后會執(zhí)行BeanPostProcessor接口的postProcessAfterInitialization方法,AbstractAutoProxyCreator的postProcessAfterInitialization就會判斷是否需要為當(dāng)前Bean生成代理,那是怎么做的呢?

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                // Transaction注解就會在這里生成代理類
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

AbstractAutoProxyCreator的postProcessAfterInitialization方法會判斷是否需要為當(dāng)前正在創(chuàng)建的Bean創(chuàng)建一個(gè)代理的包裝類。

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

        // 如果使用了Transaction注解這里就會返回?cái)r截器,返回BeanFactoryTransactionAttributeSourceAdvisor
        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            // 創(chuàng)建代理
            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;
    }

主要關(guān)注getAdvicesAndAdvisorsForBean方法,在AbstractAdvisorAutoProxyCreator類中,會調(diào)用findEligibleAdvisors方法查找符合要求的Advisor。

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
        // 查找候選advisor
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        // 使用AopUtils.findAdvisorsThatCanApply判斷時(shí)候能應(yīng)用
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

findEligibleAdvisors方法會通過findCandidateAdvisors查找spring容器中所有存在的Advisor,findCandidateAdvisors掠過不分析,其實(shí)也很簡單,可以自己分析(主要調(diào)用的是AnnotationAwareAspectJAutoProxyCreator的findCandidateAdvisors)。主要分析findAdvisorsThatCanApply方法。

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
        if (candidateAdvisors.isEmpty()) {
            return candidateAdvisors;
        }
        List<Advisor> eligibleAdvisors = new ArrayList<>();
        for (Advisor candidate : candidateAdvisors) {
            // IntroductionAdvisor是為每個(gè)對象做的代理,事務(wù)是針對每個(gè)類的,這個(gè)不會成立
            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;
            }
            // 主要是在這里看是否能夠應(yīng)用
            if (canApply(candidate, clazz, hasIntroductions)) {
                eligibleAdvisors.add(candidate);
            }
        }
        return eligibleAdvisors;
    }

調(diào)用當(dāng)前類的canApply方法判斷Advisor是否適合當(dāng)前Bean。

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

那么這里的PointcutAdvisor又是哪一個(gè)類的功能呢?

3.分析TransactionManagementConfigurationSelector

是否還記得之前的在TransactionManagementConfigurationSelector導(dǎo)入了兩個(gè)類,一個(gè)是AutoProxyRegistrar,我們已經(jīng)分析了,另一個(gè)就是ProxyTransactionManagementConfiguration,
在ProxyTransactionManagementConfiguration會創(chuàng)建BeanFactoryTransactionAttributeSourceAdvisor,AnnotationTransactionAttributeSource和TransactionInterceptor這三個(gè)bean。

此時(shí)BeanFactoryTransactionAttributeSourceAdvisor就派上了用場,BeanFactoryTransactionAttributeSourceAdvisor中維護(hù)了一個(gè)pointcut:TransactionAttributeSourcePointcut,canApply中返回的pointcut就是這個(gè)pointcut,那又是怎么判斷這個(gè)advisor是否適合當(dāng)前正在創(chuàng)建的Bean呢?

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;
        }
        // 這里返回TransactionAttributeSourcePointcut自己就是一個(gè)MethodMatcher,這里返回的是自己
        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;
        }

        Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
        classes.add(targetClass);
        for (Class<?> clazz : classes) {
            //獲取正在創(chuàng)建Bean的所有方法,introductionAwareMethodMatcher我們忽略,調(diào)用的是methodMatcher.matches來判斷匹配
            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;
    }

會調(diào)用methodMatcher.matches來判斷當(dāng)前正在創(chuàng)建的Bean的每一個(gè)方法是否能應(yīng)用當(dāng)前Advisor,我們再來看這個(gè)matches方法:

public boolean matches(Method method, Class<?> targetClass) {
        if (TransactionalProxy.class.isAssignableFrom(targetClass)) {
            return false;
        }
        TransactionAttributeSource tas = getTransactionAttributeSource();
        return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
    }

而getTransactionAttributeSource()方法中返回的就是ProxyTransactionManagementConfiguration中創(chuàng)建的另一個(gè)Bean:AnnotationTransactionAttributeSource,讓我們再來看AnnotationTransactionAttributeSource的getTransactionAttribute方法,AnnotationTransactionAttributeSource繼承了AbstractFallbackTransactionAttributeSource,真正使用的是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.
        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 {
            // 通過這里計(jì)算是否存在Transaction注解,其他代碼是在做緩存,避免重復(fù)計(jì)算
            // We need to work it out.
            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.isTraceEnabled()) {
                    logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
                }
                this.attributeCache.put(cacheKey, txAttr);
            }
            return txAttr;
        }
    }

我們只看這個(gè)方法中的TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);這一行代碼,其他代碼是在做緩存,避免重復(fù)計(jì)算,computeTransactionAttribute會使用子類實(shí)現(xiàn)的findTransactionAttribute來查找注解,最終會調(diào)用determineTransactionAttribute來查找注解。

protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
        if (ae.getAnnotations().length > 0) {
            for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
                TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
                if (attr != null) {
                    return attr;
                }
            }
        }
        return null;
    }

AnnotationTransactionAttributeSource初始化時(shí)會添加SpringTransactionAnnotationParser,這里的parseTransactionAnnotation調(diào)用的就是SpringTransactionAnnotationParser的parseTransactionAnnotation方法。

public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
        // 查找方法使用了@Transactional相關(guān)的屬性
        AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
                element, Transactional.class, false, false);
        if (attributes != null) {
            // 將所有注解屬性拼成一個(gè)RuleBasedTransactionAttribute返回
            return parseTransactionAnnotation(attributes);
        }
        else {
            return null;
        }
    }

如果存在Tranction注解,最終parseTransactionAnnotation會返回一個(gè)RuleBasedTransactionAttribute,里面包含了@Transaction的相關(guān)屬性比如傳播行為,隔離級別等,后面事務(wù)管理相關(guān)文章會分析這個(gè)類。
返回RuleBasedTransactionAttribute后,canApply方法就會返回true,讓我們再回到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;
        }

        // 如果使用了Transaction注解這里就會返回?cái)r截器,返回BeanFactoryTransactionAttributeSourceAdvisor
        // Create proxy if we have advice.
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
            // 創(chuàng)建代理
            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;
    }

canApply返回true后,getAdvicesAndAdvisorsForBean就會將BeanFactoryTransactionAttributeSourceAdvisor作為符合要求的Advisor返回,接下來就進(jìn)入了創(chuàng)建代理的過程,我們知道一個(gè)Advisor中真正對方法調(diào)用起作用的是Advice,而BeanFactoryTransactionAttributeSourceAdvisor使用的Advice就是ProxyTransactionManagementConfiguration中創(chuàng)建的最后一個(gè)Bean:TransactionInterceptor。

創(chuàng)建完代理后返回postProcessAfterInitialization,spring就會用這個(gè)被代理的對象替換之前傳入的Bean,這樣就為添加了Transaction注解的Bean添加了代理,引入了事務(wù)管理功能。

下一篇文章我們再來看看TransactionInterceptor是怎么起作用的。

寫在最后

本篇文章是springboot事務(wù)管理的第一篇,鑒于本人才疏學(xué)淺,如有不對之處歡迎指正,包括文章的錯誤和分析的思路等等,大家一起進(jìn)步。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容