<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring源碼閱讀,@Transactional實現(xiàn)原理

          共 8747字,需瀏覽 18分鐘

           ·

          2022-03-18 15:21

          你知道的越多,不知道的就越多,業(yè)余的像一棵小草!

          你來,我們一起精進!你不來,我和你的競爭對手一起精進!

          編輯:業(yè)余草

          blog.csdn.net/qq_20597727

          推薦:https://www.xttblog.com/?p=5319

          @Transactional注解簡介

          @Transactional是spring中聲明式事務管理的注解配置方式,相信這個注解的作用大家都很清楚。@Transactional注解可以幫助我們把事務開啟、提交或者回滾的操作,通過aop的方式進行管理。通過@Transactional注解就能讓spring為我們管理事務,免去了重復的事務管理邏輯,減少對業(yè)務代碼的侵入,使我們開發(fā)人員能夠專注于業(yè)務層面開發(fā)。

          @Transactional注解

          我們知道實現(xiàn)@Transactional原理是基于spring aop,aop又是動態(tài)代理模式的實現(xiàn),通過對源碼的閱讀,總結出下面的步驟來了解實際中,在spring 是如何利用aop來實現(xiàn)@Transactional的功能的。如果對spring的aop實現(xiàn)原理不了解,可以看aop實現(xiàn)原理分析。

          spring中聲明式事務實現(xiàn)原理猜想

          1. 首先,對于spring中aop實現(xiàn)原理有了解的話,應該知道想要對一個方法進行代理的話,肯定需要定義切點。在@Transactional的實現(xiàn)中,同樣如此,spring為我們定義了以 @Transactional 注解為植入點的切點,這樣才能知道@Transactional注解標注的方法需要被代理。
          2. 有了切面定義之后,在spring的bean的初始化過程中,就需要對實例化的bean進行代理,并且生成代理對象。
          3. 生成代理對象的代理邏輯中,進行方法調用時,需要先獲取切面邏輯,@Transactional注解的切面邏輯類似于@Around,在spring中是實現(xiàn)一種類似代理邏輯。
          @Transactional的實現(xiàn)

          @Transactional作用

          根據(jù)上面的原理猜想,下面簡單介紹每個步驟的源碼以進行驗證。

          首先是@Transactional,作用是定義代理植入點。【aop實現(xiàn)原理分析】中,分析知道代理對象創(chuàng)建的通過BeanPostProcessor的實現(xiàn)類AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInstantiation方法來實現(xiàn)個,如果需要進行代理,那么在這個方法就會返回一個代理對象給容器,同時判斷植入點也是在這個方法中。

          那么下面開始分析,在配置好注解驅動方式的事務管理之后,spring會在ioc容器創(chuàng)建一個「BeanFactoryTransactionAttributeSourceAdvisor實例,這個實例可以看作是一個切點,在判斷一個bean在初始化過程中是否需要創(chuàng)建代理對象,都需要驗證一次BeanFactoryTransactionAttributeSourceAdvisor是否是適用這個bean的切點。如果是,就需要創(chuàng)建代理對象,并且把BeanFactoryTransactionAttributeSourceAdvisor實例注入到代理對象中。」

          其中【aop實現(xiàn)原理分析】知道在AopUtils#findAdvisorsThatCanApply中判斷切面是否適用當前bean,可以在這個地方斷點分析調用堆棧,AopUtils#findAdvisorsThatCanApply一致調用,最終通過以下代碼判斷是否適用切點。

          • AbstractFallbackTransactionAttributeSource#computeTransactionAttribute(Method method, Class targetClass)這里可以根據(jù)參數(shù)打上條件斷點進行調試分析調用棧,targetClass就是目標class
            • …一系列調用
          • 最終SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement)
          @Override
          public?TransactionAttribute?parseTransactionAnnotation(AnnotatedElement?ae)?{
          ????//這里就是分析Method是否被@Transactional注解標注,有的話,不用說BeanFactoryTransactionAttributeSourceAdvisor適配當前bean,進行代理,并且注入切點
          ????//BeanFactoryTransactionAttributeSourceAdvisor
          ???AnnotationAttributes?attributes?=?AnnotatedElementUtils.getMergedAnnotationAttributes(ae,?Transactional.class);
          ???if?(attributes?!=?null)?{
          ??????return?parseTransactionAnnotation(attributes);
          ???}
          ???else?{
          ??????return?null;
          ???}
          }

          上面就是判斷是否需要根據(jù)@Transactional進行代理對象創(chuàng)建的判斷過程。@Transactional的作用一個就是標識方法需要被代理,一個就是攜帶事務管理需要的一些屬性信息。

          動態(tài)代理邏輯實現(xiàn)

          【aop實現(xiàn)原理分析】中知道,aop最終的代理對象的代理方法是

          • DynamicAdvisedInterceptor#intercept

          所以我們可以在這個方法斷點分析代理邏輯。

          @Override
          public?Object?intercept(Object?proxy,?Method?method,?Object[]?args,?MethodProxy?methodProxy)?throws?Throwable?{
          ???Object?oldProxy?=?null;
          ???boolean?setProxyContext?=?false;
          ???Class?targetClass?=?null;
          ???Object?target?=?null;
          ???try?{
          ??????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?=?getTarget();
          ??????if?(target?!=?null)?{
          ?????????targetClass?=?target.getClass();
          ??????}
          ???????//follow
          ??????List?chain?=?this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,?targetClass);
          ??????Object?retVal;
          ??????//?Check?whether?we?only?have?one?InvokerInterceptor:?that?is,
          ??????//?no?real?advice,?but?just?reflective?invocation?of?the?target.
          ??????if?(chain.isEmpty()?&&?Modifier.isPublic(method.getModifiers()))?{
          ?????????//?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.
          ?????????Object[]?argsToUse?=?AopProxyUtils.adaptArgumentsIfNecessary(method,?args);
          ?????????retVal?=?methodProxy.invoke(target,?argsToUse);
          ??????}
          ??????else?{
          ?????????//?We?need?to?create?a?method?invocation...
          ?????????retVal?=?new?CglibMethodInvocation(proxy,?target,?method,?args,?targetClass,?chain,?methodProxy).proceed();
          ??????}
          ??????retVal?=?processReturnType(proxy,?target,?method,?retVal);
          ??????return?retVal;
          ???}
          ???finally?{
          ??????if?(target?!=?null)?{
          ?????????releaseTarget(target);
          ??????}
          ??????if?(setProxyContext)?{
          ?????????//?Restore?old?proxy.
          ?????????AopContext.setCurrentProxy(oldProxy);
          ??????}
          ???}
          }

          通過分析 List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)返回的是TransactionInterceptor,利用「TransactionInterceptor」是如何實現(xiàn)代理邏輯調用的?

          跟蹤new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

          發(fā)現(xiàn)最終是調用TransactionInterceptor#invoke方法,并且把CglibMethodInvocation注入到invoke方法中,從上面可以看到CglibMethodInvocation是包裝了目標對象的方法調用的所有必須信息,因此,在TransactionInterceptor#invoke里面也是可以調用目標方法的,并且還可以實現(xiàn)類似@Around的邏輯,在目標方法調用前后繼續(xù)注入一些其他邏輯,比如事務管理邏輯。

          TransactionInterceptor–最終事務管理者

          下面看代碼。

          • TransactionInterceptor#invoke
          @Override
          public?Object?invoke(final?MethodInvocation?invocation)?throws?Throwable?{
          ?//?Work?out?the?target?class:?may?be?{@code?null}.
          ?//?The?TransactionAttributeSource?should?be?passed?the?target?class
          ?//?as?well?as?the?method,?which?may?be?from?an?interface.
          ?Class?targetClass?=?(invocation.getThis()?!=?null???AopUtils.getTargetClass(invocation.getThis())?:?null);

          ?//?Adapt?to?TransactionAspectSupport's?invokeWithinTransaction...
          ?return?invokeWithinTransaction(invocation.getMethod(),?targetClass,?new?InvocationCallback()?{
          ??@Override
          ??public?Object?proceedWithInvocation()?throws?Throwable?{
          ???return?invocation.proceed();
          ??}
          ?});
          }

          繼續(xù)跟蹤invokeWithinTransaction,下面的代碼中其實就可以看出一些邏輯端倪,就是我們猜想的實現(xiàn)方式,事務管理。

          protected?Object?invokeWithinTransaction(Method?method,?Class?targetClass,?final?InvocationCallback?invocation)
          ??????throws?Throwable?
          {

          ???//?If?the?transaction?attribute?is?null,?the?method?is?non-transactional.
          ???final?TransactionAttribute?txAttr?=?getTransactionAttributeSource().getTransactionAttribute(method,?targetClass);
          ???final?PlatformTransactionManager?tm?=?determineTransactionManager(txAttr);
          ???final?String?joinpointIdentification?=?methodIdentification(method,?targetClass);

          ???if?(txAttr?==?null?||?!(tm?instanceof?CallbackPreferringPlatformTransactionManager))?{
          ??????//?Standard?transaction?demarcation?with?getTransaction?and?commit/rollback?calls.
          ???????//開啟事務
          ??????TransactionInfo?txInfo?=?createTransactionIfNecessary(tm,?txAttr,?joinpointIdentification);
          ??????Object?retVal?=?null;
          ??????try?{
          ?????????//?This?is?an?around?advice:?Invoke?the?next?interceptor?in?the?chain.
          ?????????//?This?will?normally?result?in?a?target?object?being?invoked.
          ??????????//方法調用
          ?????????retVal?=?invocation.proceedWithInvocation();
          ??????}
          ??????catch?(Throwable?ex)?{
          ?????????//?target?invocation?exception
          ?????//回滾事務
          ?????????completeTransactionAfterThrowing(txInfo,?ex);
          ?????????throw?ex;
          ??????}
          ??????finally?{
          ?????????cleanupTransactionInfo(txInfo);
          ??????}
          ???????//提交事務
          ??????commitTransactionAfterReturning(txInfo);
          ??????return?retVal;
          ???}

          ???else?{
          ??????//?It's?a?CallbackPreferringPlatformTransactionManager:?pass?a?TransactionCallback?in.
          ??????try?{
          ?????????Object?result?=?((CallbackPreferringPlatformTransactionManager)?tm).execute(txAttr,
          ???????????????new?TransactionCallback()?{
          ??????????????????@Override
          ??????????????????public?Object?doInTransaction(TransactionStatus?status)?{
          ?????????????????????TransactionInfo?txInfo?=?prepareTransactionInfo(tm,?txAttr,?joinpointIdentification,?status);
          ?????????????????????try?{
          ????????????????????????return?invocation.proceedWithInvocation();
          ?????????????????????}
          ?????????????????????catch?(Throwable?ex)?{
          ????????????????????????if?(txAttr.rollbackOn(ex))?{
          ???????????????????????????//?A?RuntimeException:?will?lead?to?a?rollback.
          ???????????????????????????if?(ex?instanceof?RuntimeException)?{
          ??????????????????????????????throw?(RuntimeException)?ex;
          ???????????????????????????}
          ???????????????????????????else?{
          ??????????????????????????????throw?new?ThrowableHolderException(ex);
          ???????????????????????????}
          ????????????????????????}
          ????????????????????????else?{
          ???????????????????????????//?A?normal?return?value:?will?lead?to?a?commit.
          ???????????????????????????return?new?ThrowableHolder(ex);
          ????????????????????????}
          ?????????????????????}
          ?????????????????????finally?{
          ????????????????????????cleanupTransactionInfo(txInfo);
          ?????????????????????}
          ??????????????????}
          ???????????????});

          ?????????//?Check?result:?It?might?indicate?a?Throwable?to?rethrow.
          ?????????if?(result?instanceof?ThrowableHolder)?{
          ????????????throw?((ThrowableHolder)?result).getThrowable();
          ?????????}
          ?????????else?{
          ????????????return?result;
          ?????????}
          ??????}
          ??????catch?(ThrowableHolderException?ex)?{
          ?????????throw?ex.getCause();
          ??????}
          ???}
          }

          總結

          最終可以總結一下整個流程,跟開始的猜想對照。

          分析源碼后對照

          分析源碼后對照

          分析源碼后對照

          瀏覽 59
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    精品人妻无码一区二区三区四川人 | 午夜777 | 波多野吉衣在线观看免费天堂 | 天天色天天操天天 | 四虎性爱网站 |