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

我們知道實現(xiàn)@Transactional原理是基于spring aop,aop又是動態(tài)代理模式的實現(xiàn),通過對源碼的閱讀,總結(jié)出下面的步驟來了解實際中,在spring 是如何利用aop來實現(xiàn)@Transactional的功能的。
spring中聲明式事務實現(xiàn)原理猜想
首先,對于spring中aop實現(xiàn)原理有了解的話,應該知道想要對一個方法進行代理的話,肯定需要定義切點。在@Transactional的實現(xiàn)中,同樣如此,spring為我們定義了以 @Transactional 注解為植入點的切點,這樣才能知道@Transactional注解標注的方法需要被代理。
有了切面定義之后,在spring的bean的初始化過程中,就需要對實例化的bean進行代理,并且生成代理對象。
生成代理對象的代理邏輯中,進行方法調(diào)用時,需要先獲取切面邏輯,@Transactional注解的切面邏輯類似于@Around,在spring中是實現(xiàn)一種類似代理邏輯。

@Transactional作用
根據(jù)上面的原理猜想,下面簡單介紹每個步驟的源碼以進行驗證。
首先是@Transactional,作用是定義代理植入點。我們知道代理對象創(chuàng)建的通過BeanPostProcessor的實現(xiàn)類AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInstantiation方法來實現(xiàn)個,如果需要進行代理,那么在這個方法就會返回一個代理對象給容器,同時判斷植入點也是在這個方法中。
那么下面開始分析,在配置好注解驅(qū)動方式的事務管理之后,spring會在ioc容器創(chuàng)建一個BeanFactoryTransactionAttributeSourceAdvisor實例,這個實例可以看作是一個切點,在判斷一個bean在初始化過程中是否需要創(chuàng)建代理對象,都需要驗證一次BeanFactoryTransactionAttributeSourceAdvisor是否是適用這個bean的切點。如果是,就需要創(chuàng)建代理對象,并且把BeanFactoryTransactionAttributeSourceAdvisor實例注入到代理對象中。
前文我們知道在AopUtils#findAdvisorsThatCanApply中判斷切面是否適用當前bean,可以在這個地方斷點分析調(diào)用堆棧,AopUtils#findAdvisorsThatCanApply一致調(diào)用,最終通過以下代碼判斷是否適用切點。
AbstractFallbackTransactionAttributeSource#computeTransactionAttribute(Method method, Class> targetClass)?這里可以根據(jù)參數(shù)打上條件斷點進行調(diào)試分析調(diào)用棧,targetClass就是目標class …一系列調(diào)用最終 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通過分析?List返回的是TransactionInterceptor,利用TransactionInterceptor是如何實現(xiàn)代理邏輯調(diào)用的?
跟蹤new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
發(fā)現(xiàn)最終是調(diào)用TransactionInterceptor#invoke方法,并且把CglibMethodInvocation注入到invoke方法中,從上面可以看到CglibMethodInvocation是包裝了目標對象的方法調(diào)用的所有必須信息,因此,在TransactionInterceptor#invoke里面也是可以調(diào)用目標方法的,并且還可以實現(xiàn)類似@Around的邏輯,在目標方法調(diào)用前后繼續(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.
??????????//方法調(diào)用
?????????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總結(jié)
最終可以總結(jié)一下整個流程,跟開始的猜想對照。

分析源碼后對照

感謝閱讀,希望對你有所幫助?:)?
來源:blog.csdn.net/qq_20597727/article/details/84868035
推薦閱讀:
不是你需要中臺,而是一名合格的架構(gòu)師(附各大廠中臺建設PPT)
企業(yè)IT技術(shù)架構(gòu)規(guī)劃方案
論數(shù)字化轉(zhuǎn)型——轉(zhuǎn)什么,如何轉(zhuǎn)?
企業(yè)10大管理流程圖,數(shù)字化轉(zhuǎn)型從業(yè)者必備!
【中臺實踐】華為大數(shù)據(jù)中臺架構(gòu)分享.pdf
