美文网首页
springboot事务管理源码分析--1.启动分析

springboot事务管理源码分析--1.启动分析

作者: jxxiangwen | 来源:发表于2019-01-22 14:54 被阅读0次

    本文基于springboot(1.5以上)的事务管理的开篇,主要关于Transaction注解的生效过程

    Transaction注解怎么生效

    springboot开启事务管理需要在启动类加上@EnableTransactionManagement,EnableTransactionManagement使用@Import导入TransactionManagementConfigurationSelector类,TransactionManagementConfigurationSelector实现了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;
            }
        }
    

    默认情况下是proxy 模式,会导入AutoProxyRegistrar(将InfrastructureAdvisorAutoProxyCreator纳入spring管理,但是后续会被高优先级的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函数所在的Application类中加了EnableTransactionManagement注解
                // 下面这个判断就会成立,默认情况下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是一个实现了ImportBeanDefinitionRegistrar接口的类, AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)会将InfrastructureAdvisorAutoProxyCreator加入了spring管理,但是真正用来创建代理的是AnnotationAwareAspectJAutoProxyCreator类,看下面这张继承关系图,两者都继承了AbstractAdvisorAutoProxyCreator,主要功能是类似的,那么AnnotationAwareAspectJAutoProxyCreator又是什么时候引入spring容器的呢?

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

    这里就要涉及springboot是怎么实现自动配置的了。@SpringBootApplication会引入@EnableAutoConfiguration,这个注解会使用@Import导入 EnableAutoConfigurationImportSelector,此类的父类AutoConfigurationImportSelector实现了ImportSelector,在selectImports方法中使用AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader)导入META-INF/spring-autoconfigure-metadata.properties,导入@EnableAspectJAutoProxy,而@EnableAspectJAutoProxy又使用@Import导入了AspectJAutoProxyRegistrar,在这个类的selectImports会注册上AnnotationAwareAspectJAutoProxyCreator这个Bean,也就是说其实只要是springboot项目都会导入这个Bean,而由于在AopConfigUtils将AnnotationAwareAspectJAutoProxyCreator和InfrastructureAdvisorAutoProxyCreator做了排序,如果存在AnnotationAwareAspectJAutoProxyCreator,那么InfrastructureAdvisorAutoProxyCreator就不会生效。

    那什么时候会为加了Transaction注解的方法或者类加上事务管理功能呢?

    2.分析AnnotationAwareAspectJAutoProxyCreator

    AnnotationAwareAspectJAutoProxyCreator实现了AbstractAutoProxyCreator抽象类,AbstractAutoProxyCreator又实现了BeanPostProcessor接口,熟悉spring IOC的都知道在每个Bean执行完初始化方法后会执行BeanPostProcessor接口的postProcessAfterInitialization方法,AbstractAutoProxyCreator的postProcessAfterInitialization就会判断是否需要为当前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方法会判断是否需要为当前正在创建的Bean创建一个代理的包装类。

    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注解这里就会返回拦截器,返回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);
                // 创建代理
                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方法,在AbstractAdvisorAutoProxyCreator类中,会调用findEligibleAdvisors方法查找符合要求的Advisor。

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
            // 查找候选advisor
            List<Advisor> candidateAdvisors = findCandidateAdvisors();
            // 使用AopUtils.findAdvisorsThatCanApply判断时候能应用
            List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
            extendAdvisors(eligibleAdvisors);
            if (!eligibleAdvisors.isEmpty()) {
                eligibleAdvisors = sortAdvisors(eligibleAdvisors);
            }
            return eligibleAdvisors;
        }
    

    findEligibleAdvisors方法会通过findCandidateAdvisors查找spring容器中所有存在的Advisor,findCandidateAdvisors掠过不分析,其实也很简单,可以自己分析(主要调用的是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是为每个对象做的代理,事务是针对每个类的,这个不会成立
                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;
                }
                // 主要是在这里看是否能够应用
                if (canApply(candidate, clazz, hasIntroductions)) {
                    eligibleAdvisors.add(candidate);
                }
            }
            return eligibleAdvisors;
        }
    

    调用当前类的canApply方法判断Advisor是否适合当前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又是哪一个类的功能呢?

    3.分析TransactionManagementConfigurationSelector

    是否还记得之前的在TransactionManagementConfigurationSelector导入了两个类,一个是AutoProxyRegistrar,我们已经分析了,另一个就是ProxyTransactionManagementConfiguration,
    在ProxyTransactionManagementConfiguration会创建BeanFactoryTransactionAttributeSourceAdvisor,AnnotationTransactionAttributeSource和TransactionInterceptor这三个bean。

    此时BeanFactoryTransactionAttributeSourceAdvisor就派上了用场,BeanFactoryTransactionAttributeSourceAdvisor中维护了一个pointcut:TransactionAttributeSourcePointcut,canApply中返回的pointcut就是这个pointcut,那又是怎么判断这个advisor是否适合当前正在创建的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自己就是一个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) {
                //获取正在创建Bean的所有方法,introductionAwareMethodMatcher我们忽略,调用的是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;
        }
    

    会调用methodMatcher.matches来判断当前正在创建的Bean的每一个方法是否能应用当前Advisor,我们再来看这个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中创建的另一个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 {
                // 通过这里计算是否存在Transaction注解,其他代码是在做缓存,避免重复计算
                // 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;
            }
        }
    

    我们只看这个方法中的TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);这一行代码,其他代码是在做缓存,避免重复计算,computeTransactionAttribute会使用子类实现的findTransactionAttribute来查找注解,最终会调用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初始化时会添加SpringTransactionAnnotationParser,这里的parseTransactionAnnotation调用的就是SpringTransactionAnnotationParser的parseTransactionAnnotation方法。

    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
            // 查找方法使用了@Transactional相关的属性
            AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
                    element, Transactional.class, false, false);
            if (attributes != null) {
                // 将所有注解属性拼成一个RuleBasedTransactionAttribute返回
                return parseTransactionAnnotation(attributes);
            }
            else {
                return null;
            }
        }
    

    如果存在Tranction注解,最终parseTransactionAnnotation会返回一个RuleBasedTransactionAttribute,里面包含了@Transaction的相关属性比如传播行为,隔离级别等,后面事务管理相关文章会分析这个类。
    返回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注解这里就会返回拦截器,返回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);
                // 创建代理
                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返回,接下来就进入了创建代理的过程,我们知道一个Advisor中真正对方法调用起作用的是Advice,而BeanFactoryTransactionAttributeSourceAdvisor使用的Advice就是ProxyTransactionManagementConfiguration中创建的最后一个Bean:TransactionInterceptor。

    创建完代理后返回postProcessAfterInitialization,spring就会用这个被代理的对象替换之前传入的Bean,这样就为添加了Transaction注解的Bean添加了代理,引入了事务管理功能。

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

    写在最后

    本篇文章是springboot事务管理的第一篇,鉴于本人才疏学浅,如有不对之处欢迎指正,包括文章的错误和分析的思路等等,大家一起进步。

    相关文章

      网友评论

          本文标题:springboot事务管理源码分析--1.启动分析

          本文链接:https://www.haomeiwen.com/subject/lmzkjqtx.html