Spring 註解事務處理流程源碼分析

聲明:本文是自己在學習Spring註解事務處理源代碼時所留下的筆記; 難免有錯誤,敬請讀者諒解!!!

1、事務註解標籤

    <tx:annotation-driven />

2、tx 命名空間解析器
事務tx命名空間解析器TxNamespaceHandler
org.springframework.transaction.config.TxNamespaceHandler#init

這裏寫圖片描述

3、AnnotationDrivenBeanDefinitionParser#parse 解析事務標籤

(1)、以下方法的核心邏輯主要是選擇是否使用 Aspect 方式實現代理,默認方式爲 JDK 的動態代理。
org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser#parse

public BeanDefinition parse(Element element, ParserContext parserContext) {
    String mode = element.getAttribute("mode");
    if ("aspectj".equals(mode)) {
        // mode="aspectj"
        registerTransactionAspect(element, parserContext);
    }
    else {
        // mode="proxy"   注意 AopAutoProxyConfigurer 爲當前內的內部類
        AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
    }
    return null;
}

(2)、進入如下方法,該方法的核心邏輯通過硬編碼的方式配置 Aop 動態代理的解析器
AopAutoProxyConfigurer#configureAutoProxyCreator
通過硬編碼,Spring 爲我們定義瞭如下的 Spring BeanDefinition 對象
(a)、AnnotationTransactionAttributeSource.class 事務註解屬性解析器BeanDefinition 對象。
AnnotationTransactionAttributeSource 構造方法會初始化:

public AnnotationTransactionAttributeSource() {
        this(true);
}

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
    this.publicMethodsOnly = publicMethodsOnly;
    this.annotationParsers = new LinkedHashSet<TransactionAnnotationParser>(2);
    this.annotationParsers.add(new SpringTransactionAnnotationParser());// @Transactional 註解解析器
    if (ejb3Present) {
        this.annotationParsers.add(new Ejb3TransactionAnnotationParser());// Ejb 解析器
    }

(b)、TransactionInterceptor.class 事務攔截器BeanDefinition 對象
(c)、BeanFactoryTransactionAttributeSourceAdvisor.class 事務切面解析器
(d)、TransactionInterceptor.class 事務攔截器BeanDefinition 對象
(e)、容易忽略的第一行代碼:AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element); 在這個方法內部 Spring 爲我們的注入了:InfrastructureAdvisorAutoProxyCreator.class
這裏寫圖片描述

private static class AopAutoProxyConfigurer {

    public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {

        // 非常重要的一行代碼,在這個裏面註冊了:InfrastructureAdvisorAutoProxyCreator.class 該類實現了Spring BeanProcessor 的擴展接口
        AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

        String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
        if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
            Object eleSource = parserContext.extractSource(element);

            // Create the TransactionAttributeSource definition.
            RootBeanDefinition sourceDef = new RootBeanDefinition(AnnotationTransactionAttributeSource.class);// 事務註解解析器
            sourceDef.setSource(eleSource);
            sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

            // Create the TransactionInterceptor definition.
            RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);//事務攔截器
            interceptorDef.setSource(eleSource);
            interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            registerTransactionManager(element, interceptorDef);
            interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
            String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

            // Create the TransactionAttributeSourceAdvisor definition.
            RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);//事務切面解析器
            advisorDef.setSource(eleSource);
            advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            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);

            CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
            compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
            compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
            compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
            parserContext.registerComponent(compositeDef);
        }
    }
}

4、Spring Bean 實例化創建代理對象
(a)、AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

這裏寫圖片描述

(b)、AbstractAutoProxyCreator#postProcessAfterInitialization
這裏寫圖片描述

還記得上面我們提到的 InfrastructureAdvisorAutoProxyCreator 的類圖吧,最後我們的 @Transactional 註解的類會執行該類中的 postProcessAfterInitialization 方法

(c)、Bean 的初始化後置處理,通過註釋可以瞭解到,當前方法處理後會返回一個 bean 的代理對象

/**
 * Create a proxy with the configured interceptors if the bean is
 * identified as one to proxy by the subclass.
 * @see #getAdvicesAndAdvisorsForBean
 */
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.containsKey(cacheKey)) {
            return wrapIfNecessary(bean, beanName, cacheKey);// 創建代理類的核心方法
        }
    }
    return bean;
}

(d)、AbstractAutoProxyCreator#wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (beanName != null && this.targetSourcedBeans.containsKey(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);

        // 創建代理對象,默認的情況下會使用 JDK 的動態代理接口創建代理對象
        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;
}

(c)、獲取到的事務切面
org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#computeTransactionAttribute
這裏寫圖片描述

(d)、事務切面獲取邏輯
這裏寫圖片描述

(e)、委託 ProxyFactory 創建代理對象

protected Object createProxy(
        Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

    ProxyFactory proxyFactory = new ProxyFactory();
    // Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
    proxyFactory.copyFrom(this);

    if (!shouldProxyTargetClass(beanClass, beanName)) {
        // Must allow for introductions; can't just set interfaces to
        // the target's interfaces only.
        Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
        for (Class<?> targetInterface : targetInterfaces) {
            proxyFactory.addInterface(targetInterface);
        }
    }

    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
    for (Advisor advisor : advisors) {
        proxyFactory.addAdvisor(advisor);
    }

    proxyFactory.setTargetSource(targetSource);
    customizeProxyFactory(proxyFactory);

    proxyFactory.setFrozen(this.freezeProxy);
    if (advisorsPreFiltered()) {
        proxyFactory.setPreFiltered(true);
    }

    // 最終會使用:JdkDynamicAopProxy  創建事務的Aop 代理對象
    return proxyFactory.getProxy(this.proxyClassLoader);
}

(f)、最終生成代理對象
這裏寫圖片描述

5、代理類執行
JdkDynamicAopProxy#invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    MethodInvocation invocation;
    Object oldProxy = null;
    boolean setProxyContext = false;

    TargetSource targetSource = this.advised.targetSource;
    Class<?> targetClass = null;
    Object target = null;

    try {
        // 如果目標方法沒有實現equals
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            // The target does not implement the equals(Object) method itself.
            return equals(args[0]);
        }
        // 如果目標方法沒有實現hashcode
        if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            // The target does not implement the hashCode() method itself.
            return hashCode();
        }
        // 根據代理對象的配置來調用服務
        if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            // Service invocations on ProxyConfig with the proxy config...
            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
        }

        Object retVal;

        if (this.advised.exposeProxy) {
            // Make invocation available if necessary.
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }

        // May be null. Get as late as possible to minimize the time we "own" the target,
        // in case it comes from a pool.
        // 獲取目標對象
        target = targetSource.getTarget();
        if (target != null) {
            targetClass = target.getClass();
        }

        // 獲取定義好的攔截器鏈
        // Get the interception chain for this method.
        List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

        // Check whether we have any advice. If we don't, we can fallback on direct
        // reflective invocation of the target, and avoid creating a MethodInvocation.
        if (chain.isEmpty()) {
            // We can skip creating a MethodInvocation: just invoke the target directly
            // Note that the final invoker must be an InvokerInterceptor so we know it does
            // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
            // 沒有攔截鏈則直接調用target方法
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
        }
        else {
            // We need to create a method invocation...
            //對攔截鏈進行封裝  得到對象ReflectiveMethodInvocation 調用 proceed 方法
            invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // Proceed to the joinpoint through the interceptor chain.
            retVal = invocation.proceed();// 方法內部將執行攔截器的切面直到目標方法被執行
        }

        // Massage return value if necessary.
        Class<?> returnType = method.getReturnType();
        if (retVal != null && retVal == target && returnType.isInstance(proxy) &&
                !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
            // Special case: it returned "this" and the return type of the method
            // is type-compatible. Note that we can't help if the target sets
            // a reference to itself in another returned object.
            retVal = proxy;
        }
        else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
            throw new AopInvocationException(
                    "Null return value from advice does not match primitive return type for: " + method);
        }
        return retVal;
    }
    finally {
        if (target != null && !targetSource.isStatic()) {
            // Must have come from TargetSource.
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}

7、代理會執行到: ReflectiveMethodInvocation#proceed 方法

8、最終會執行到:TransactionInterceptor#invoke 方法

這裏寫圖片描述

9、執行 TransactionAspectSupport 事務方法
TransactionInterceptor#invoke 方法會調用到父類的 TransactionAspectSupport#invokeWithinTransaction 方法

這裏寫圖片描述

10、業務方法執行
這裏寫圖片描述

11、Spring 事務處理的流程
這裏寫圖片描述

(a)、開啓事務
這裏寫圖片描述

(b)、事務回滾
這裏寫圖片描述

(c)、事務提交
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章