Spring事務是如何應用到你的業務場景中的?

 

初衷

平常開發中常常用到@Transaction註解,那你知道它是怎麼應用到你的業務代碼中的嗎?本篇文章將從如下兩個方面闡述Spring事務實現原理:java

  1. 解析並加載事務配置:本質上是解析xml文件將標籤加載成 BeanDefinition 對象;node

  2. 生成事務代理對象並運行:本質上是Spring AOP在事務這塊的應用,將業務Bean替換成事務代理對象(JdkDynamicAopProxy:JDK代理,CglibAopProxy:CGLIB代理);spring

本文使用的源碼版本是Spring 4.3.18.RELEASE,使用的是XML開啓事務。bootstrap

關鍵類

這裏列出幾個核心類,提早留個印象,後面會講解何時調用緩存

  1. XmlBeanDefinitionReader 加載XML定義的Bean入口app

  2. TxNamespaceHandler 解析XML中的事務標籤:advice、annotation-driven等;ide

  3. InfrastructureAdvisorAutoProxyCreator 該類實現了 BeanPostProcessor 接口(能夠在Bean初始化後進行替換),是生成事務代理類並替換的關鍵類;函數

  4. AnnotationTransactionAttributeSource 用來解析業務方法使用註解 @Transaction 上的配置,提供給 TransactionInterceptor 使用;post

  5. TransactionInterceptor 事務攔截類:真正處理事務的類,開啓、回滾事務,能夠理解成切面中的通知:作什麼;優化

  6. BeanFactoryTransactionAttributeSourceAdvisor 實現了Advisor接口,能夠理解爲切面:切點(TransactionAttributeSourcePointcut) + 通知(TransactionInterceptor)。

示例代碼:
public class TransactionService {
      @Transactional(rollbackFor = Throwable.class)      public void testTransaction(){          System.out.println("方法邏輯");      }  }
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml");     TransactionService transactionService = context.getBean(TransactionService.class);     transactionService.testTransaction();
<beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:aop="http://www.springframework.org/schema/aop"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:jee="http://www.springframework.org/schema/jee"       xmlns:tx="http://www.springframework.org/schema/tx"       xmlns:task="http://www.springframework.org/schema/task"       xsi:schemaLocation="        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd">    
                                        
        <bean id="transactionManager"          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
1. 解析並加載事務配置

加載的入口(同時也是Spring容器加載的核心代碼):

synchronized (this.startupShutdownMonitor) {      // Prepare this context for refreshing.      prepareRefresh();
      // 重點,這裏是Spring初始化默認的容器,在這一步會經過解析配置文件將定義的bean轉換爲 BeanDefinition,      // 保存在 beanDefinitionMap 中      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      // Prepare the bean factory for use in this context.      prepareBeanFactory(beanFactory);
      try {        // Allows post-processing of the bean factory in context subclasses.        postProcessBeanFactory(beanFactory);
        // Invoke factory processors registered as beans in the context.        invokeBeanFactoryPostProcessors(beanFactory);
        // Register bean processors that intercept bean creation.        registerBeanPostProcessors(beanFactory);
        // Initialize message source for this context.        initMessageSource();
        // Initialize event multicaster for this context.        initApplicationEventMulticaster();
        // Initialize other special beans in specific context subclasses.        onRefresh();
        // Check for listener beans and register them.        registerListeners();
        // 重點,初始化全部非懶加載bean的方法,也能夠理解爲根據特定規則將 BeanDefinition 轉成 Bean對象的方法        finishBeanFactoryInitialization(beanFactory);
        // Last step: publish corresponding event.        finishRefresh();      }
      catch (BeansException ex) {        if (logger.isWarnEnabled()) {          logger.warn("Exception encountered during context initialization - " +              "cancelling refresh attempt: " + ex);        }
        // Destroy already created singletons to avoid dangling resources.        destroyBeans();
        // Reset 'active' flag.        cancelRefresh(ex);
        // Propagate exception to caller.        throw ex;      }
      finally {        // Reset common introspection caches in Spring's core, since we        // might not ever need metadata for singleton beans anymore...        resetCommonCaches();      }    }

 

事務配置的解析在上面的obtainFreshBeanFactory,因爲咱們使用的是ClassPathXmlApplicationContext 做爲容器,它的解析類爲:XmlBeanDefinitionReader;核心方法:

 

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {    Assert.notNull(encodedResource, "EncodedResource must not be null");    if (logger.isInfoEnabled()) {      logger.info("Loading XML bean definitions from " + encodedResource.getResource());    }
    Set    if (currentResources == null) {      currentResources = new HashSet      this.resourcesCurrentlyBeingLoaded.set(currentResources);    }    if (!currentResources.add(encodedResource)) {      throw new BeanDefinitionStoreException(          "Detected cyclic loading of " + encodedResource + " - check your import definitions!");    }    try {      // 讀取 config.xml 文件      InputStream inputStream = encodedResource.getResource().getInputStream();      try {        InputSource inputSource = new InputSource(inputStream);        if (encodedResource.getEncoding() != null) {          inputSource.setEncoding(encodedResource.getEncoding());        }        // 開始加載 config.xml 文件中定義的bean,這裏只是加載成BeanDefinition,初始化在另外的方法        return doLoadBeanDefinitions(inputSource, encodedResource.getResource());      }      finally {        inputStream.close();      }    }    catch (IOException ex) {      throw new BeanDefinitionStoreException(          "IOException parsing XML document from " + encodedResource.getResource(), ex);    }    finally {      currentResources.remove(encodedResource);      if (currentResources.isEmpty()) {        this.resourcesCurrentlyBeingLoaded.remove();      }    }  }

 

doLoadBeanDefinitions 具體解析的方法是在org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions 中進行,該方法以下

 

protected void doRegisterBeanDefinitions(Element root) {    // Any nested    // order to propagate and preserve    // keep track of the current (parent) delegate, which may be null. Create    // the new (child) delegate with a reference to the parent for fallback purposes,    // then ultimately reset this.delegate back to its original (parent) reference.    // this behavior emulates a stack of delegates without actually necessitating one.    BeanDefinitionParserDelegate parent = this.delegate;    this.delegate = createDelegate(getReaderContext(), root, parent);
    if (this.delegate.isDefaultNamespace(root)) {      String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);      if (StringUtils.hasText(profileSpec)) {        String[] specifiedProfiles = StringUtils.tokenizeToStringArray(            profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);        if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {          if (logger.isInfoEnabled()) {            logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +                "] not matching: " + getReaderContext().getResource());          }          return;        }      }    }
    preProcessXml(root);    // 真正解析config.xml文件    parseBeanDefinitions(root, this.delegate);    postProcessXml(root);
    this.delegate = parent;  }
  protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {      // 判斷根節點是否是默認的節點,實際經過判斷根節點的 namespaceURI 屬性是否是 http://www.springframework.org/schema/beans ,      // 咱們這裏的配置文件聲明的正好是這個屬性,因此返回的是true,注意bean標籤也是默認標籤    if (delegate.isDefaultNamespace(root)) {      // 獲取子節點      NodeList nl = root.getChildNodes();      for (int i = 0; i < nl.getLength(); i++) {        Node node = nl.item(i);        // 判斷子節點是否是標籤        if (node instanceof Element) {          Element ele = (Element) node;          // bean標籤的解析          if (delegate.isDefaultNamespace(ele)) {            parseDefaultElement(ele, delegate);          }          // 重點:tx標籤在這裏進行          else {            delegate.parseCustomElement(ele);          }        }      }    }    else {      delegate.parseCustomElement(root);    }  }  // 解析非bean的標籤  public BeanDefinition parseCustomElement(Element ele) {    return parseCustomElement(ele, null);  }  // 解析非默認標籤方法  public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {    String namespaceUri = getNamespaceURI(ele);    // 這裏是Spring使用了策略模式解析配置,經過namespaceUri匹配對應的處理類,也就是上面的關鍵類 TxNamespaceHandler,    // 這裏的resolve運用了懶加載,在獲取映射關係handlerMappings屬性爲null時會從META-INF/spring.handlers 下面獲取映射關係,    // 因爲IDEA debug的時候默認會調用getHandlerMappings方法,因此使用debug的時候會發現一開始就有值    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);    if (handler == null) {      error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);      return null;    }    // 獲取處處理類後,讓處理類開始解析配置    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));  }

TxNamespaceHandler 最終交給類 AnnotationDrivenBeanDefinitionParser 進行解析事務配置;

 

public BeanDefinition parse(Element element, ParserContext parserContext) {    // 註冊一個事務工廠事件,容許咱們自定義監聽事務的提交等操做    registerTransactionalEventListenerFactory(parserContext);    String mode = element.getAttribute("mode");    // 若是使用的是 aspectj 方式,走這個方法    if ("aspectj".equals(mode)) {      // mode="aspectj"      registerTransactionAspect(element, parserContext);    }    else {      // 默認使用的是代理模式       // mode="proxy"      AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);    }    return null;  }
  /**   * Inner class to just introduce an AOP framework dependency when actually in proxy mode.   */  private static class AopAutoProxyConfigurer {
    public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {      // 重點,註冊 InfrastructureAdvisorAutoProxyCreator 的 BeanDefinition,這個是個關鍵類,代理業務bean的操做都靠它了      AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
      String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;      if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {        Object eleSource = parserContext.extractSource(element);
        // 重點,註冊一個全局的 TransactionAttributeSource 的BeanDefinition ,用於解析 @Transaction 定義的元數據        RootBeanDefinition sourceDef = new RootBeanDefinition(            "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");        sourceDef.setSource(eleSource);        sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);        String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
        // 重點,註冊 TransactionInterceptor 的BeanDefinition,這個就是事務真正執行的類,能夠理解爲是事務切面上的通知        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);
        // 重點,註冊 BeanFactoryTransactionAttributeSourceAdvisor 的BeanDefinition,能夠理解爲事務的切面,        // 包含了切點(TransactionAttributeSourcePointcut) + 通知(TransactionInterceptor),保存在 ProxyFactory 中,用於生成代理對象        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);      }    }  }

到這裏,事務配置的加載就結束了,上面的步驟只是將事務的關鍵類變成 BeanDefinition,實際上尚未生成Bean對象的,下面咱們看下BeanDefinition 是如何變成Bean的(這一個步驟不是Spring事務獨有的,是全部BeanDefinition 的共同邏輯),而後是如何生成業務bean代理對象並替換業務bean的。

2. 生成事務代理對象

入口在 1.解析並加載事務配置 列舉的finishBeanFactoryInitialization(beanFactory) 方法中:

/**   * Finish the initialization of this context's bean factory,   * initializing all remaining singleton beans.   */  protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {    // Initialize conversion service for this context.    if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&        beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {      beanFactory.setConversionService(          beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));    }
    // Register a default embedded value resolver if no bean post-processor    // (such as a PropertyPlaceholderConfigurer bean) registered any before:    // at this point, primarily for resolution in annotation attribute values.    if (!beanFactory.hasEmbeddedValueResolver()) {      beanFactory.addEmbeddedValueResolver(new StringValueResolver() {        @Override        public String resolveStringValue(String strVal) {          return getEnvironment().resolvePlaceholders(strVal);        }      });    }
    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);    for (String weaverAwareName : weaverAwareNames) {      getBean(weaverAwareName);    }
    // Stop using the temporary ClassLoader for type matching.    beanFactory.setTempClassLoader(null);
    // Allow for caching all bean definition metadata, not expecting further changes.    beanFactory.freezeConfiguration();
    // 重點,開始初始化全部非懶加載的bean    beanFactory.preInstantiateSingletons();  }

beanFactory.preInstantiateSingletons() 具體方法以下:

 

public void preInstantiateSingletons() throws BeansException {    if (this.logger.isDebugEnabled()) {      this.logger.debug("Pre-instantiating singletons in " + this);    }
    // Iterate over a copy to allow for init methods which in turn register new bean definitions.    // While this may not be part of the regular factory bootstrap, it does otherwise work fine.將全部註冊的BeanDefinition 名稱保存到起來    List
    // Trigger initialization of all non-lazy singleton beans...    for (String beanName : beanNames) {      // 獲取 BeanDefinition      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);      // bean定義不是抽象、懶加載並且是單例bean      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {        // 工廠bean特有邏輯,這不是咱們的關注點,咱們關注點是else的 getBean(beanName);        if (isFactoryBean(beanName)) {          final FactoryBean          boolean isEagerInit;          if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {            isEagerInit = AccessController.doPrivileged(new PrivilegedAction              @Override              public Boolean run() {                return ((SmartFactoryBean              }            }, getAccessControlContext());          }          else {            isEagerInit = (factory instanceof SmartFactoryBean &&                ((SmartFactoryBean          }          if (isEagerInit) {            getBean(beanName);          }        }        else {          // 重點,將 BeanDefinition 建立成bean的核心方法,同時也是執行 BeanPostProcessor 的入口          getBean(beanName);        }      }    }
    // Trigger post-initialization callback for all applicable beans...    for (String beanName : beanNames) {      Object singletonInstance = getSingleton(beanName);      if (singletonInstance instanceof SmartInitializingSingleton) {        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;        if (System.getSecurityManager() != null) {          AccessController.doPrivileged(new PrivilegedAction            @Override            public Object run() {              smartSingleton.afterSingletonsInstantiated();              return null;            }          }, getAccessControlContext());        }        else {          smartSingleton.afterSingletonsInstantiated();        }      }    }  }

getBean(beanName) 方法比較複雜,這裏只列舉出關鍵點:AbstractAutowireCapableBeanFactory 的 initializeBean方法,全部bean的建立都繞不開這個方法,這個方法是執行實現了 BeanPostProcessor 的bean的邏輯:

 

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {    if (System.getSecurityManager() != null) {      AccessController.doPrivileged(new PrivilegedAction        @Override        public Object run() {          invokeAwareMethods(beanName, bean);          return null;        }      }, getAccessControlContext());    }    else {      invokeAwareMethods(beanName, bean);    }
    Object wrappedBean = bean;    if (mbd == null || !mbd.isSynthetic()) {      // 執行 BeanPostProcessor 的 postProcessBeforeInitialization 方法      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);    }
    try {      invokeInitMethods(beanName, wrappedBean, mbd);    }    catch (Throwable ex) {      throw new BeanCreationException(          (mbd != null ? mbd.getResourceDescription() : null),          beanName, "Invocation of init method failed", ex);    }    if (mbd == null || !mbd.isSynthetic()) {      // 重點,InfrastructureAdvisorAutoProxyCreator 實現了BeanPostProcessor 接口,因此這裏會調用 InfrastructureAdvisorAutoProxyCreator 的postProcessBeforeInitialization 方法,      // wrappedBean 是生成代理後對象,wrappedBean 會替換掉傳入的bean,若是當前bean須要事務,wrappedBean就是被JDK或者CGLIB代理後的bean      wrappedBean = postProcessAfterInitialization(wrappedBean, beanName);    }    return wrappedBean;  }

InfrastructureAdvisorAutoProxyCreator 的 postProcessAfterInitialization 定義在父類:AbstractAutoProxyCreator,AbstractAutoProxyCreator這個類同時是Spring AOP處理的入口,並非說事務處理獨有的,具體實現以下:

 

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {    if (bean != null) {      Object cacheKey = getCacheKey(bean.getClass(), beanName);      if (!this.earlyProxyReferences.contains(cacheKey)) {        // 重點,AOP生成代理對象的入口,這裏也會生成事務代理對象        return wrapIfNecessary(bean, beanName, cacheKey);      }    }    return bean;  }
  // 從Spring容器中獲取全部切面bean,並判斷是否在切面中,若是是的話生成一個代理對象,怎麼代理由具體的切面定義  protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {    if (beanName != null && this.targetSourcedBeans.contains(beanName)) {      return bean;    }    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {      return bean;    }    // 這裏就是用來判斷當前bean 能不能代理    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {      this.advisedBeans.put(cacheKey, Boolean.FALSE);      return bean;    }
    // 首先查找切面Bean,對於本篇文章就是咱們上面定義的 BeanFactoryTransactionAttributeSourceAdvisor 的 BeanDefinition,注意:實際應用場景確定不只只有一個切面的。    // spring如今只有BeanDefinition,這個方法先經過獲取切面 beanNames ,而後再調用上面的 getBean 方法生成 BeanFactoryTransactionAttributeSourceAdvisor bean對象    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());      // 返回代理後的bean      return proxy;    }
    this.advisedBeans.put(cacheKey, Boolean.FALSE);    // 不代理,返回原始bean    return bean;  }
  // 獲取切面bean,先經過獲取切面BeanNames ,而後經過獲取bean  protected Object[] getAdvicesAndAdvisorsForBean(Class    List    if (advisors.isEmpty()) {      return DO_NOT_PROXY;    }    return advisors.toArray();  }
  protected List    // 這個方法就是獲取切面bean,首先從容器中獲取實現了 Advisor 的beanNames,而後經過beanName再獲取Bean,    // 對於本篇文章只定義了一個事務切面,因此這裏返回的結果是 BeanFactoryTransactionAttributeSourceAdvisor Bean對象    List    // 判斷當前bean是否能被切面應用,判斷規則在下面有說明    List    extendAdvisors(eligibleAdvisors);    if (!eligibleAdvisors.isEmpty()) {      eligibleAdvisors = sortAdvisors(eligibleAdvisors);    }    return eligibleAdvisors;  }
  // findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName) 具體實現邏輯在org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply   public static List    if (candidateAdvisors.isEmpty()) {      return candidateAdvisors;    }    List    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 processed        continue;      }      if (canApply(candidate, clazz, hasIntroductions)) {        eligibleAdvisors.add(candidate);      }    }    return eligibleAdvisors;  }
  //  請注意,這個方法是AOP通用判斷是否能應用切面的方法,不是事務處理獨有的  public static boolean canApply(Pointcut pc, Class    Assert.notNull(pc, "Pointcut must not be null");    // 首先判斷類能不能匹配上,匹配不上就返回false, BeanFactoryTransactionAttributeSourceAdvisor 的切點類:    // TransactionAttributeSourcePointcut,默認ClassFilter 返回true,因此這裏不會進if    if (!pc.getClassFilter().matches(targetClass)) {      return false;    }
    // 而後判斷方法匹配,TransactionAttributeSourcePointcut 經過繼承關係能夠看到不是 MethodMatcher.TRUE,因此不會進if    MethodMatcher methodMatcher = pc.getMethodMatcher();    if (methodMatcher == MethodMatcher.TRUE) {      // No need to iterate the methods if we're matching any method anyway...      return true;    }
    // 判斷是否是引介方法匹配,什麼是引介加強:爲目標類追加方法,屬於類的加強,    // 而 PointcutAdvisor 屬於攔截目標類的方法並加強,TransactionAttributeSourcePointcut  是 PointcutAdvisor 的子類,不屬於引介加強    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;    if (methodMatcher instanceof IntroductionAwareMethodMatcher) {      introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;    }
    // 開始讀取目標類的每個方法,判斷是否在切面中    Set<Class    classes.add(targetClass);    for (Class      Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);      for (Method method : methods) {        // 對於事務而言,判斷條件重點在 TransactionAttributeSourcePointcut 的 matches 方法        if ((introductionAwareMethodMatcher != null &&            introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||            methodMatcher.matches(method, targetClass)) {          return true;        }      }    }
    return false;  }   // TransactionAttributeSourcePointcut 的 matches 方法核心邏輯在 SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement)  // 注意:只會判斷 public 的方法,判斷有沒有 Transactional 註解;判斷的順序爲:先判斷方法上面有沒有,再判斷類上面有沒有。  // 判斷核心就是看方法或類上面有沒有 Transactional 註解,有這個註解就解析這個註解的元數據  public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {    AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class);    if (attributes != null) {      return parseTransactionAnnotation(attributes);    }    else {      return null;    }  }  // 解析 Transactional  註解元數據  protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {    RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();    Propagation propagation = attributes.getEnum("propagation");    rbta.setPropagationBehavior(propagation.value());    Isolation isolation = attributes.getEnum("isolation");    rbta.setIsolationLevel(isolation.value());    rbta.setTimeout(attributes.getNumber("timeout").intValue());    rbta.setReadOnly(attributes.getBoolean("readOnly"));    rbta.setQualifier(attributes.getString("value"));    ArrayList    Class    for (Class      RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);      rollBackRules.add(rule);    }    String[] rbfc = attributes.getStringArray("rollbackForClassName");    for (String rbRule : rbfc) {      RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);      rollBackRules.add(rule);    }    Class    for (Class      NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);      rollBackRules.add(rule);    }    String[] nrbfc = attributes.getStringArray("noRollbackForClassName");    for (String rbRule : nrbfc) {      NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);      rollBackRules.add(rule);    }    rbta.getRollbackRules().addAll(rollBackRules);    return rbta;  }  // 以上就是 findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName) 的邏輯
  // 下面回到wrapIfNecessary方法,若是當前bean須要生成代理對象,會調用下面的這個方法  protected Object createProxy(      Class
    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {      AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);    }
    // 建立代理工廠,用於建立代理bean    ProxyFactory proxyFactory = new ProxyFactory();    proxyFactory.copyFrom(this);
    // 判斷是否配置了代理目標類,配置了這個選項會所有使用cglib代理    if (!proxyFactory.isProxyTargetClass()) {      if (shouldProxyTargetClass(beanClass, beanName)) {        proxyFactory.setProxyTargetClass(true);      }      else {        evaluateProxyInterfaces(beanClass, proxyFactory);      }    }    // 把全部的切面類放入 ProxyFactory    Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);    proxyFactory.addAdvisors(advisors);    proxyFactory.setTargetSource(targetSource);    customizeProxyFactory(proxyFactory);
    proxyFactory.setFrozen(this.freezeProxy);    if (advisorsPreFiltered()) {      proxyFactory.setPreFiltered(true);    }
    // 開始建立代理bean    return proxyFactory.getProxy(getProxyClassLoader());  }

proxyFactory.getProxy(getProxyClassLoader()) 方法實現:

 

public Object getProxy(ClassLoader classLoader) {    return createAopProxy().getProxy(classLoader);  }
  // createAopProxy方法邏輯,config 其實就是上面的 proxyFactory 對象,這個對象包含了目標對象以及切面類:  public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {    // optimize:代理是否應該執行優化,通常用不上    // proxyTargetClass:這個屬性爲treu時,無論目標類是否是實現的接口,都使用cglib代理    // hasNoUserSuppliedProxyInterfaces:是否只使用了Spring支持的代理接口,若是用戶自定義了代理接口不能進行cglib代理    if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {      Class      if (targetClass == null) {        throw new AopConfigException("TargetSource cannot determine target class: " +            "Either an interface or a target is required for proxy creation.");      }      // 若是目標類是接口或者已經被jdk代理過了,使用jdk代理      if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {        return new JdkDynamicAopProxy(config);      }      // 其餘狀況使用CGLIB代理      return new ObjenesisCglibAopProxy(config);    }    // 使用JDK代理    else {      return new JdkDynamicAopProxy(config);    }  }
  // ObjenesisCglibAopProxy 的 getProxy(classLoader) 方法,cglib是使用Enhancer建立代理對象的 :  public Object getProxy(ClassLoader classLoader) {    if (logger.isDebugEnabled()) {      logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());    }
    try {      // 獲取目標類      Class      Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");      // 代理類的父類,默認是目標類      Class      // 若是目標類以及是cglib代理類,      if (ClassUtils.isCglibProxyClass(rootClass)) {        // 取cglib代理類的父類做爲代理類的父類        proxySuperClass = rootClass.getSuperclass();        // 獲取代理類的接口追加到當前類的接口集合中        Class        for (Class          this.advised.addInterface(additionalInterface);        }      }
      // 驗證目標類是否能被代理,僅僅是打印日誌,不作其餘處理      validateClassIfNecessary(proxySuperClass, classLoader);
      // 使用Enhancer 來構造cglib代理對象      Enhancer enhancer = createEnhancer();      if (classLoader != null) {        enhancer.setClassLoader(classLoader);        if (classLoader instanceof SmartClassLoader &&            ((SmartClassLoader) classLoader).isCla***eloadable(proxySuperClass)) {          enhancer.setUseCache(false);        }      }      enhancer.setSuperclass(proxySuperClass);      enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));      enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);      enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
      // 重點,設置回調的類,很重要的一個類 DynamicAdvisedInterceptor,這個類就是應用AOP 通知的地方,對於本篇文章就是應用TransactionInterceptor      Callback[] callbacks = getCallbacks(rootClass);      Class      for (int x = 0; x < types.length; x++) {        types[x] = callbacks[x].getClass();      }      // fixedInterceptorMap only populated at this point, after getCallbacks call above      enhancer.setCallbackFilter(new ProxyCallbackFilter(          this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));      enhancer.setCallbackTypes(types);
      // 建立代理類的字節碼,並建立實例,實例設置回調      return createProxyClassAndInstance(enhancer, callbacks);    }    catch (CodeGenerationException ex) {      throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +          ": Common causes of this problem include using a final class or a non-visible class",          ex);    }    catch (IllegalArgumentException ex) {      throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +          ": Common causes of this problem include using a final class or a non-visible class",          ex);    }    catch (Throwable ex) {      // TargetSource.getTarget() failed      throw new AopConfigException("Unexpected AOP exception", ex);    }  }

// JdkDynamicAopProxy  的 getProxy(classLoader) 方法:public Object getProxy(ClassLoader classLoader) {    if (logger.isDebugEnabled()) {      logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());    }    Class    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);  }

經過2. 生成事務代理對象,此時建立的bean就是以及被JDK或者CGLIB代理的類,這一步是Spring AOP通用的處理邏輯,那具體是怎麼運行的呢?

JDK動態代理運行:

 

// 本質是調用org.springframework.aop.framework.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    Object target = null;
    try {      if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {        // The target does not implement the equals(Object) method itself.        return equals(args[0]);      }      else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {        // The target does not implement the hashCode() method itself.        return hashCode();      }      else if (method.getDeclaringClass() == DecoratingProxy.class) {        // There is only getDecoratedClass() declared -> dispatch to proxy config.        return AopProxyUtils.ultimateTargetClass(this.advised);      }      else 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();      }
      // 獲取方法的攔截器鏈,對於本篇文章就是關鍵類:BeanFactoryTransactionAttributeSourceAdvisor      List
      // 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.        Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);        retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);      }      else {        // 將全部參數:代理對象,目標對象,方法,參數,攔截器鏈封裝到一個ReflectiveMethodInvocation對象中        invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);        // 而後調用ReflectiveMethodInvocation的proceed方法,會執行攔截器        retVal = invocation.proceed();      }
      // Massage return value if necessary.      Class      if (retVal != null && retVal == target &&          returnType != Object.class && 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);      }    }  }

org.springframework.aop.framework.ReflectiveMethodInvocation#proceed 方法:

 

public Object proceed() throws Throwable {    // 全部攔截器調用完成,通常狀況是沒有匹配到任意的攔截器,這裏會執行目標類自己的方法    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {      return invokeJoinpoint();    }
    // 獲取攔截器鏈中的第一個攔截器    Object interceptorOrInterceptionAdvice =        this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);    // 通知器或通知是動態匹配方法攔截器類型,對於本篇文章,interceptorOrInterceptionAdvice 是TransactionInterceptor對象,    // 全部走的是else,直接執行TransactionInterceptor的invoke方法    if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {      // 動態匹配方法攔截器      InterceptorAndDynamicMethodMatcher dm =          (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;      // 匹配成功就執行對應的攔截器      if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {        return dm.interceptor.invoke(this);      }      else {        // 若是不匹配,就跳過此攔截器,遞歸執行下一個攔截器        return proceed();      }    }    else {      // 若是是一個interceptor,直接調用這個interceptor對應的方法      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);    }  }

CGLIB代理運行:

 

// 其實就是建立代理對象時設置的回調類DynamicAdvisedInterceptor  private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
    private final AdvisedSupport advised;
    public DynamicAdvisedInterceptor(AdvisedSupport advised) {      this.advised = advised;    }
    // 主要是這個方法執行攔截,處理邏輯大體和JDK動態代理差很少,都是獲取攔截器鏈,    // 而後構建ReflectiveMethodInvocation的子類CglibMethodInvocation對象,    // 執行ReflectiveMethodInvocation的proceed方法    @Override    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {      Object oldProxy = null;      boolean setProxyContext = false;      Class      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();        }        // 獲取方法的攔截器鏈,對於本篇文章就是關鍵類:BeanFactoryTransactionAttributeSourceAdvisor        List        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 {          // 將參數封裝成CglibMethodInvocation對象並執行proceed方法,CglibMethodInvocation 實際上是ReflectiveMethodInvocation的子類,能夠理解爲ReflectiveMethodInvocation是模板類,CglibMethodInvocation經過重寫了部分方法,proceed是兩種代理處理的共同邏輯          retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();        }        retVal = proce***eturnType(proxy, target, method, retVal);        return retVal;      }      finally {        if (target != null) {          releaseTarget(target);        }        if (setProxyContext) {          // Restore old proxy.          AopContext.setCurrentProxy(oldProxy);        }      }    }
    @Override    public boolean equals(Object other) {      return (this == other ||          (other instanceof DynamicAdvisedInterceptor &&              this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));    }
    /**     * CGLIB uses this to drive proxy creation.     */    @Override    public int hashCode() {      return this.advised.hashCode();    }
    protected Object getTarget() throws Exception {      return this.advised.getTargetSource().getTarget();    }
    protected void releaseTarget(Object target) throws Exception {      this.advised.getTargetSource().releaseTarget(target);    }  }

事務的最終執行類 TransactionInterceptor 的invoke 方法:

 

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
    // Adapt to TransactionAspectSupport's invokeWithinTransaction...    return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {      @Override      public Object proceedWithInvocation() throws Throwable {        // 事務執行完畢後調用鏈繼續向下執行        return invocation.proceed();      }    });  }
  protected Object invokeWithinTransaction(Method method, Class      throws Throwable {
    // 獲取當前方法的事務屬性    final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);    // 獲取事務管理器    final PlatformTransactionManager tm = determineTransactionManager(txAttr);    // 方法名    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
    // 若是方法沒有事務或者事務管理器不屬於CallbackPreferringPlatformTransactionManager,CallbackPreferringPlatformTransactionManager須要回調函數來實現事務流程,而咱們經常使用的DataSourceTransactionManager就不是CallbackPreferringPlatformTransactionManager    if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {      // 建立TransactionInfo事務對象,事務的管理都是經過TransactionInfo對象來完成,這裏建立事務會使用到Spring的事務隔離級別,具體的邏輯能夠自行查看      TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);      Object retVal = null;      try {        // 攔截器鏈繼續向下執行        retVal = invocation.proceedWithInvocation();      }      catch (Throwable ex) {        // 拋出異常時提交或者回滾事務        completeTransactionAfterThrowing(txInfo, ex);        throw ex;      }      finally {        // 重置TransactionInfo 的 ThreadLocal        cleanupTransactionInfo(txInfo);      }      // 提交/回滾事務      commitTransactionAfterReturning(txInfo);      return retVal;    }    // else使用的是CallbackPreferringPlatformTransactionManager,    else {      // .......略    }  }
總結

以上就是事務應用到業務場景中的原理,能夠簡單理解:Spring事務是在Spring AOP的基礎上開發的,關注關鍵類:TransactionInterceptor 的實現就好了,不論是JDK動態代理仍是CGLIB代理都是要用到這個類去提交/回滾事務的。若有錯誤歡迎指出。

相關文章
相關標籤/搜索