spring5 源碼深度解析----- Spring事務 是怎麼經過AOP實現的?(100%理解Spring事務)

做者:chen_haophp

 

 

正文java

此篇文章須要有SpringAOP基礎,知道AOP底層原理能夠更好的理解Spring的事務處理。spring

自定義標籤

對於Spring中事務功能的代碼分析,咱們首先從配置文件開始人手,在配置文件中有這樣一個配置:<tx:annotation-driven/>。能夠說此處配置是事務的開關,若是沒有此處配置,那麼Spring中將不存在事務的功能。那麼咱們就從這個配置開始分析。編程

根據以前的分析,咱們所以能夠判斷,在自定義標籤中的解析過程當中必定是作了一些輔助操做,因而咱們先從自定義標籤入手進行分析。使用Idea搜索全局代碼,關鍵字annotation-driven,最終鎖定類TxNamespaceHandler,在TxNamespaceHandler中的 init 方法中:數組

  •  
@Overridepublic void init() {registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());}

在遇到諸如tx:annotation-driven爲開頭的配置後,Spring都會使用AnnotationDrivenBeanDefinitionParser類的parse方法進行解析。緩存

  •  
@Override@Nullablepublic BeanDefinition parse(Element element, ParserContext parserContext) {registerTransactionalEventListenerFactory(parserContext);String mode = element.getAttribute("mode");if ("aspectj".equals(mode)) {// mode="aspectj"registerTransactionAspect(element, parserContext);if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {registerJtaTransactionAspect(element, parserContext);}}else {// mode="proxy"AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);}return null;}

在解析中存在對於mode屬性的判斷,根據代碼,若是咱們須要使用AspectJ的方式進行事務切入(Spring中的事務是以AOP爲基礎的),那麼可使用這樣的配置:app

  •  
<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>

註冊 InfrastructureAdvisorAutoProxyCreator

咱們以默認配置爲例進行分析,進人AopAutoProxyConfigurer類的configureAutoProxyCreator:框架

  •  
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {//向IOC註冊InfrastructureAdvisorAutoProxyCreator這個類型的BeanAopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {Object eleSource = parserContext.extractSource(element);
// Create the TransactionAttributeSource definition.// 建立AnnotationTransactionAttributeSource類型的BeanRootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");sourceDef.setSource(eleSource);sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
// Create the TransactionInterceptor definition.// 建立TransactionInterceptor類型的BeanRootBeanDefinition 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.// 建立BeanFactoryTransactionAttributeSourceAdvisor類型的BeanRootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);advisorDef.setSource(eleSource);advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);// 將上面AnnotationTransactionAttributeSource類型Bean注入進上面的AdvisoradvisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));// 將上面TransactionInterceptor類型Bean注入進上面的AdvisoradvisorDef.getPropertyValues().add("adviceBeanName", interceptorName);if (element.hasAttribute("order")) {advisorDef.getPropertyValues().add("order", element.getAttribute("order"));}parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);// 將上面三個Bean註冊進IOC中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);}}

這裏分別是註冊了三個Bean,和一個InfrastructureAdvisorAutoProxyCreator,其中三個Bean支撐了整個事務的功能。ide

咱們首先須要回顧一下AOP的原理,AOP中有一個 Advisor 存放在代理類中,而Advisor中有advise與pointcut信息,每次執行被代理類的方法時都會執行代理類的invoke(若是是JDK代理)方法,而invoke方法會根據advisor中的pointcut動態匹配這個方法須要執行的advise鏈,遍歷執行advise鏈,從而達到AOP切面編程的目的。函數

  • BeanFactoryTransactionAttributeSourceAdvisor:首先看這個類的繼承結構,能夠看到這個類實際上是一個Advisor,其實由名字也能看出來,類中有幾個關鍵地方注意一下,在以前的註冊過程當中,將兩個屬性注入進這個Bean中:

  •  
// 將上面AnnotationTransactionAttributeSource類型Bean注入進上面的AdvisoradvisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));// 將上面TransactionInterceptor類型Bean注入進上面的AdvisoradvisorDef.getPropertyValues().add("adviceBeanName", interceptorName);

那麼它們被注入成什麼了呢?進入BeanFactoryTransactionAttributeSourceAdvisor一看便知。

  •  
@Nullableprivate TransactionAttributeSource transactionAttributeSource;

在其父類中有屬性:

  •  
@Nullableprivate String adviceBeanName;

也就是說,這裏先將上面的TransactionInterceptor的BeanName傳入到Advisor中,而後將AnnotationTransactionAttributeSource這個Bean注入到Advisor中,那麼這個Source Bean有什麼用呢?能夠繼續看看BeanFactoryTransactionAttributeSourceAdvisor的源碼。

  •  
private final TransactionAttributeSourcePointcut pointcut = new     TransactionAttributeSourcePointcut() {@Override@Nullableprotected TransactionAttributeSource getTransactionAttributeSource() {return transactionAttributeSource;}};

看到這裏應該明白了,這裏的Source是提供了pointcut信息,做爲存放事務屬性的一個類注入進Advisor中,到這裏應該知道註冊這三個Bean的做用了吧?首先註冊pointcut、advice、advisor,而後將pointcut和advice注入進advisor中,在以後動態代理的時候會使用這個Advisor去尋找每一個Bean是否須要動態代理(取決因而否有開啓事務),由於Advisor有pointcut信息。

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

  • InfrastructureAdvisorAutoProxyCreator:在方法開頭,首先就調用了AopNamespeceUtils去註冊了這個Bean,那麼這個Bean是幹什麼用的呢?仍是先看看這個類的結構。這個類繼承了AbstractAutoProxyCreator,看到這個名字,熟悉AOP的話應該已經知道它是怎麼作的了吧?其次這個類還實現了BeanPostProcessor接口,凡事實現了這個BeanPost接口的類,咱們首先關注的就是它的postProcessAfterInitialization方法,這裏在其父類也就是剛剛提到的AbstractAutoProxyCreator這裏去實現。(這裏須要知道Spring容器初始化Bean的過程,關於BeanPostProcessor的使用我會另開一篇講解。若是不知道只需瞭解若是一個Bean實現了BeanPostProcessor接口,當全部Bean實例化且依賴注入以後初始化方法以後會執行這個實現Bean的postProcessAfterInitialization方法)

進入這個函數:

  •  
public static void registerAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);registerComponentIfNecessary(beanDefinition, parserContext);}
@Nullablepublic static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,@Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);}

對於解析來的代碼流程AOP中已經有所分析,上面的兩個函數主要目的是註冊了InfrastructureAdvisorAutoProxyCreator類型的bean,那麼註冊這個類的目的是什麼呢?查看這個類的層次,以下圖所示:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

 

從上面的層次結構中能夠看到,InfrastructureAdvisorAutoProxyCreator間接實現了SmartInstantiationAwareBeanPostProcessor,而SmartInstantiationAwareBeanPostProcessor又繼承自InstantiationAwareBeanPostProcessor,也就是說在Spring中,全部bean實例化時Spring都會保證調用其postProcessAfterInstantiation方法,其實現是在父類AbstractAutoProxyCreator類中實現。

以以前的示例爲例,當實例化AccountServiceImpl的bean時便會調用此方法,方法以下:

  •  
@Overridepublic Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {// 根據給定的bean的class和name構建出key,格式:beanClassName_beanNameObject cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.contains(cacheKey)) {// 若是它適合被代理,則須要封裝指定beanreturn wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}

 這裏實現的主要目的是對指定bean進行封裝,固然首先要肯定是否須要封裝,檢測與封裝的工做都委託給了wrapIfNecessary函數進行。

  •  
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// 若是處理過這個bean的話直接返回if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}// 以後若是Bean匹配不成功,會將Bean的cacheKey放入advisedBeans中// value爲false,因此這裏能夠用cacheKey判斷此bean是否以前已經代理不成功了if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}// 這裏會將Advise、Pointcut、Advisor類型的類過濾,直接不進行代理,returnif (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {// 這裏即爲不成功的狀況,將false放入Map中this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}
// Create proxy if we have advice.// 這裏是主要驗證的地方,傳入Bean的class與beanName去判斷此Bean有哪些AdvisorObject[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);// 若是有相應的advisor被找到,則用advisor與此bean作一個動態代理,將這兩個的信息// 放入代理類中進行代理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;}// 若是此Bean沒有一個Advisor匹配,將返回null也就是DO_NOT_PROXY// 也就是會走到這一步,將其cacheKey,false存入Map中this.advisedBeans.put(cacheKey, Boolean.FALSE);// 不代理直接返回原beanreturn bean;}

wrapIfNecessary函數功能實現起來很複雜,可是邏輯上理解起來仍是相對簡單的,在wrapIfNecessary函數中主要的工做以下:

(1)找出指定bean對應的加強器。

(2)根據找出的加強器建立代理。

聽起來彷佛簡單的邏輯,Spring中又作了哪些複雜的工做呢?對於建立代理的部分,經過以前的分析相信你們已經很熟悉了,可是對於加強器的獲取,Spring又是怎麼作的呢?

回到頂部

獲取對應class/method的加強器

獲取指定bean對應的加強器,其中包含兩個關鍵字:加強器與對應。也就是說在 getAdvicesAndAdvisorsForBean函數中,不但要找出加強器,並且還須要判斷加強器是否知足要求。

  •  
@Override@Nullableprotected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {List<Advisor> candidateAdvisors = findCandidateAdvisors();List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}

 

尋找候選加強器

  •  
protected List<Advisor> findCandidateAdvisors() {Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");return this.advisorRetrievalHelper.findAdvisorBeans();}
public List<Advisor> findAdvisorBeans() {// Determine list of advisor bean names, if not cached already.String[] advisorNames = this.cachedAdvisorBeanNames;if (advisorNames == null) {// 獲取BeanFactory中全部對應Advisor.class的類名// 這裏和AspectJ的方式有點不一樣,AspectJ是獲取全部的Object.class,而後經過反射過濾有註解AspectJ的類advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);this.cachedAdvisorBeanNames = advisorNames;}if (advisorNames.length == 0) {return new ArrayList<>();}
List<Advisor> advisors = new ArrayList<>();for (String name : advisorNames) {if (isEligibleBean(name)) {if (this.beanFactory.isCurrentlyInCreation(name)) {if (logger.isDebugEnabled()) {logger.debug("Skipping currently created advisor '" + name + "'");}}else {try {//直接獲取advisorNames的實例,封裝進advisors數組advisors.add(this.beanFactory.getBean(name, Advisor.class));}catch (BeanCreationException ex) {Throwable rootCause = ex.getMostSpecificCause();if (rootCause instanceof BeanCurrentlyInCreationException) {BeanCreationException bce = (BeanCreationException) rootCause;String bceBeanName = bce.getBeanName();if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {if (logger.isDebugEnabled()) {logger.debug("Skipping advisor '" + name +"' with dependency on currently created bean: " + ex.getMessage());}continue;}}throw ex;}}}}return advisors;}

首先是經過BeanFactoryUtils類提供的工具方法獲取全部對應Advisor.class的類,獲取辦法無非是使用ListableBeanFactory中提供的方法:

  •  
String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
 
 

在咱們講解自定義標籤時曾經註冊了一個類型爲 BeanFactoryTransactionAttributeSourceAdvisor 的 bean,而在此 bean 中咱們又注入了另外兩個Bean,那麼此時這個 Bean 就會被開始使用了。由於 BeanFactoryTransactionAttributeSourceAdvisor一樣也實現了 Advisor接口,那麼在獲取全部加強器時天然也會將此bean提取出來, 並隨着其餘加強器一塊兒在後續的步驟中被織入代理。

 

候選加強器中尋找到匹配項

當找出對應的加強器後,接下來的任務就是看這些加強器是否與對應的class匹配了,固然不僅是class,class內部的方法若是匹配也能夠經過驗證。

  •  
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {if (candidateAdvisors.isEmpty()) {return candidateAdvisors;}List<Advisor> eligibleAdvisors = new ArrayList<>();// 首先處理引介加強for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {// 引介加強已經處理if (candidate instanceof IntroductionAdvisor) {// already processedcontinue;}// 對於普通bean的處理if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}
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;}}

BeanFactoryTransactionAttributeSourceAdvisor 間接實現了PointcutAdvisor。所以,在canApply函數中的第二個if判斷時就會經過判斷,會將BeanFactoryTransactionAttributeSourceAdvisor中的getPointcut()方法返回值做爲參數繼續調用canApply方法,而 getPoint()方法返回的是TransactionAttributeSourcePointcut類型的實例。對於 transactionAttributeSource這個屬性你們還有印象嗎?這是在解析自定義標籤時注入進去的。

  •  
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {@Override@Nullableprotected TransactionAttributeSource getTransactionAttributeSource() {return transactionAttributeSource;}};

那麼,使用TransactionAttributeSourcePointcut類型的實例做爲函數參數繼續跟蹤canApply。

  •  
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;}
// 此時的pc表示TransactionAttributeSourcePointcut// pc.getMethodMatcher()返回的正是自身(this)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<>();if (!Proxy.isProxyClass(targetClass)) {classes.add(ClassUtils.getUserClass(targetClass));}//獲取對應類的全部接口classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));//對類進行遍歷for (Class<?> clazz : classes) {//反射獲取類中全部的方法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;}

經過上面函數大體能夠理清大致脈絡,首先獲取對應類的全部接口並連同類自己一塊兒遍歷,遍歷過程當中又對類中的方法再次遍歷,一旦匹配成功便認爲這個類適用於當前加強器。

到這裏咱們不由會有疑問,對於事物的配置不只僅侷限於在函數上配置,咱們都知道,在類或接口上的配置能夠延續到類中的每一個函數,那麼,若是針對每一個函數迸行檢測,在類自己上配罝的事務屬性豈不是檢測不到了嗎?帶着這個疑問,咱們繼續探求matcher方法。

作匹配的時候 methodMatcher.matches(method, targetClass)會使用 TransactionAttributeSourcePointcut 類的 matches 方法。

  •  
@Overridepublic boolean matches(Method method, Class<?> targetClass) {if (TransactionalProxy.class.isAssignableFrom(targetClass)) {return false;}// 自定義標籤解析時注入TransactionAttributeSource tas = getTransactionAttributeSource();return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);}

此時的 tas 表示 AnnotationTransactionAttributeSource 類型,這裏會判斷tas.getTransactionAttribute(method, targetClass) != null,而 AnnotationTransactionAttributeSource 類型的 getTransactionAttribute 方法以下:

  •  
@Override@Nullablepublic TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {if (method.getDeclaringClass() == Object.class) {return null;}
Object cacheKey = getCacheKey(method, targetClass);Object cached = this.attributeCache.get(cacheKey);//先從緩存中獲取TransactionAttributeif (cached != null) {if (cached == NULL_TRANSACTION_ATTRIBUTE) {return null;}else {return (TransactionAttribute) cached;}}else {// 若是緩存中沒有,工做又委託給了computeTransactionAttribute函數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.isDebugEnabled()) {logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);}//加入緩存中this.attributeCache.put(cacheKey, txAttr);}return txAttr;}}

嘗試從緩存加載,若是對應信息沒有被緩存的話,工做又委託給了computeTransactionAttribute函數,在computeTransactionAttribute函數中咱們終於看到了事務標籤的提取過程。

 

提取事務標籤

  •  
@Nullableprotected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {// Don't allow no-public methods as required.if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {return null;}
// The method may be on an interface, but we need attributes from the target class.// If the target class is null, the method will be unchanged.// method表明接口中的方法,specificMethod表明實現類中的方法Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// First try is the method in the target class.// 查看方法中是否存在事務聲明TransactionAttribute txAttr = findTransactionAttribute(specificMethod);if (txAttr != null) {return txAttr;}
// Second try is the transaction attribute on the target class.// 查看方法所在類中是否存在事務聲明txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {return txAttr;}
// 若是存在接口,則到接口中去尋找if (specificMethod != method) {// Fallback is to look at the original method.// 查找接口方法txAttr = findTransactionAttribute(method);if (txAttr != null) {return txAttr;}// Last fallback is the class of the original method.// 到接口中的類中去尋找txAttr = findTransactionAttribute(method.getDeclaringClass());if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {return txAttr;}}
return null;}

對於事務屬性的獲取規則相信你們都已經很清楚,若是方法中存在事務屬性,則使用方法上的屬性,不然使用方法所在的類上的屬性,若是方法所在類的屬性上仍是沒有搜尋到對應的事務屬性,那麼在搜尋接口中的方法,再沒有的話,最後嘗試搜尋接口的類上面的聲明。對於函數computeTransactionAttribute中的邏輯與咱們所認識的規則並沒有差別,可是上面函數中並無真正的去作搜尋事務屬性的邏輯,而是搭建了個執行框架,將搜尋事務屬性的任務委託給了 findTransactionAttribute 方法去執行。

  •  
@Override@Nullableprotected TransactionAttribute findTransactionAttribute(Class<?> clazz) {return determineTransactionAttribute(clazz);}
@Nullableprotected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {for (TransactionAnnotationParser annotationParser : this.annotationParsers) {TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);if (attr != null) {return attr;}}return null;}

this.annotationParsers 是在當前類 AnnotationTransactionAttributeSource 初始化的時候初始化的,其中的值被加入了 SpringTransactionAnnotationParser,也就是當進行屬性獲取的時候實際上是使用 SpringTransactionAnnotationParser 類的 parseTransactionAnnotation 方法進行解析的。

  •  
@Override@Nullablepublic TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(ae, Transactional.class, false, false);if (attributes != null) {return parseTransactionAnnotation(attributes);}else {return null;}}

至此,咱們終於看到了想看到的獲取註解標記的代碼。首先會判斷當前的類是否含有 Transactional註解,這是事務屬性的基礎,固然若是有的話會繼續調用parseTransactionAnnotation 方法解析詳細的屬性。

  •  
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();Propagation propagation = attributes.getEnum("propagation");// 解析propagationrbta.setPropagationBehavior(propagation.value());Isolation isolation = attributes.getEnum("isolation");// 解析isolationrbta.setIsolationLevel(isolation.value());// 解析timeoutrbta.setTimeout(attributes.getNumber("timeout").intValue());// 解析readOnlyrbta.setReadOnly(attributes.getBoolean("readOnly"));// 解析valuerbta.setQualifier(attributes.getString("value"));ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<>();// 解析rollbackForClass<?>[] rbf = attributes.getClassArray("rollbackFor");for (Class<?> rbRule : rbf) {RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);rollBackRules.add(rule);}// 解析rollbackForClassNameString[] rbfc = attributes.getStringArray("rollbackForClassName");for (String rbRule : rbfc) {RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);rollBackRules.add(rule);}// 解析noRollbackForClass<?>[] nrbf = attributes.getClassArray("noRollbackFor");for (Class<?> rbRule : nrbf) {NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);rollBackRules.add(rule);}// 解析noRollbackForClassNameString[] nrbfc = attributes.getStringArray("noRollbackForClassName");for (String rbRule : nrbfc) {NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);rollBackRules.add(rule);}rbta.getRollbackRules().addAll(rollBackRules);return rbta;}

至此,咱們終於完成了事務標籤的解析。回顧一下,咱們如今的任務是找出某個加強器是否適合於對應的類,而是否匹配的關鍵則在因而否從指定的類或類中的方法中找到對應的事務屬性,如今,咱們以AccountServiceImpl爲例,已經在它的接口AccountServiceImp中找到了事務屬性,因此,它是與事務加強器匹配的,也就是它會被事務功能修飾。

至此,事務功能的初始化工做便結束了,當判斷某個bean適用於事務加強時,也就是適用於加強器BeanFactoryTransactionAttributeSourceAdvisor

BeanFactoryTransactionAttributeSourceAdvisor 做爲 Advisor 的實現類,天然要聽從 Advisor 的處理方式,當代理被調用時會調用這個類的加強方法,也就是此bean的Advice,又由於在解析事務定義標籤時咱們把Transactionlnterceptor類的bean注人到了 BeanFactoryTransactionAttributeSourceAdvisor中,因此,在調用事務加強器加強的代理類時會首先執行Transactionlnterceptor進行加強,同時,也就是在Transactionlnterceptor類中的invoke方法中完成了整個事務的邏輯。

 

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

相關文章
相關標籤/搜索