免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
spring源碼分析之——spring 事務(wù)管理實現(xiàn)方式 (不太清晰,不明白aop會看不懂)

注意:這里只是分析spring事務(wù)的實現(xiàn)方式。也就是spring的事務(wù)管理是怎么發(fā)生作用的,而不分析具體的實現(xiàn)細節(jié)(細節(jié)將在下一篇里面分析).

 轉(zhuǎn)載:http://michael-softtech.iteye.com/blog/813835

緊接著上一篇提到的,Spring是通過NameSpaceHandler來解析配置文件中的標簽的。下面就已事務(wù)的配置為例,講述一下

事務(wù)配置的標簽的解析過程,從來理解事物是如何通過aop產(chǎn)生作用的。

 

Java代碼  
  1. <!-- 以AspectJ方式 定義 AOP -->  
  2. <aop:config proxy-target-class="true">  
  3.     <aop:advisor pointcut="execution(* commo.base.BaseManager.*(..))" advice-ref="txAdvice"/>  
  4.     <aop:advisor pointcut="execution(* com.*..*.service.*Manager.*(..))" advice-ref="txAdvice"/>  
  5. </aop:config>  
  6.   
  7. <!-- 基本事務(wù)定義,使用transactionManager作事務(wù)管理,默認get* find*方法的事務(wù)為readonly,其余方法按默認設(shè)置.  
  8.          默認的設(shè)置請參考Spring文檔事務(wù)一章. -->  
  9. <tx:advice id="txAdvice" transaction-manager="transactionManager">  
  10.     <tx:attributes>  
  11.         <tx:method name="find*" read-only="true"/>  
  12.         <tx:method name="get*" read-only="true"/>  
  13.         <tx:method name="query*" read-only="true"/>  
  14.         <tx:method name="*" read-only="false"/>  
  15.     </tx:attributes>  
  16. </tx:advice>  

 以上的配置相信很多人已經(jīng)很熟悉了,在此不贅述。而是具體分析一下原理。

 先來分析<tx:advice>...</tx:advice>。

tx是TransactionNameSpace。對應(yīng)的是handler是TxNamespaceHandler.

這個類一個init方法:

 

Java代碼  
  1. public void init() {  
  2.     registerBeanDefinitionParser("advice"new TxAdviceBeanDefinitionParser());  
  3.     registerBeanDefinitionParser("annotation-driven"new AnnotationDrivenBeanDefinitionParser());  
  4.     registerBeanDefinitionParser("jta-transaction-manager"new JtaTransactionManagerBeanDefinitionParser());  
  5. }  
 

這個方法是在DefaultNamespaceHandlerResolver的resolve中調(diào)用的。在為對應(yīng)的標簽尋找namespacehandler的時候,調(diào)用這個resolve方法。resolve方法先尋找namespaceUri對應(yīng)的namespacehandler,如果找到了就先調(diào)用Init方法。

 

    OK.我們的<tx:advice>對應(yīng)的解析器也注冊了,那就是上面代碼里面的

Java代碼  
  1. new TxAdviceBeanDefinitionParser()  

    那么,這個解析器是什么時候調(diào)用的哪?

    上一篇提到了,對應(yīng)標簽解析時會先選擇namespacehandler,然后調(diào)用其parse方法。

    TxNamespaceHandler的parse方法在其父類NamespaceHandlerSupport中,代碼如下:

 

Java代碼  
  1. public BeanDefinition parse(Element element, ParserContext parserContext) {  
  2.         return findParserForElement(element, parserContext).parse(element, parserContext);  
  3.     }  

   這下明白了吧?<tx:advice>在解析出來的Document里面是一個Element,而這個Element的parse就是上面注冊了的

Java代碼  
  1. TxAdviceBeanDefinitionParser  

 現(xiàn)在這個parser的parse方法在NamespaceHandlerSupport的parse方法中被調(diào)用了,下面我們來看看這個

  TxAdviceBeanDefinitionParser的parse方法吧,這個方法在TxAdviceBeanDefinitionParser的祖父類AbstractBeanDefinitionParser中:

 

Java代碼  
  1. public final BeanDefinition parse(Element element, ParserContext parserContext) {  
  2.         AbstractBeanDefinition definition = parseInternal(element, parserContext);  
  3.         if (definition != null && !parserContext.isNested()) {  
  4.             try {  
  5.                 String id = resolveId(element, definition, parserContext);  
  6.                 if (!StringUtils.hasText(id)) {  
  7.                     parserContext.getReaderContext().error(  
  8.                             "Id is required for element '" + parserContext.getDelegate().getLocalName(element)  
  9.                                     + "' when used as a top-level tag", element);  
  10.                 }  
  11.                 String[] aliases = new String[0];  
  12.                 String name = element.getAttribute(NAME_ATTRIBUTE);  
  13.                 if (StringUtils.hasLength(name)) {  
  14.                     aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));  
  15.                 }  
  16.                 BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);  
  17.                 registerBeanDefinition(holder, parserContext.getRegistry());  
  18.                 if (shouldFireEvents()) {  
  19.                     BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);  
  20.                     postProcessComponentDefinition(componentDefinition);  
  21.                     parserContext.registerComponent(componentDefinition);  
  22.                 }  
  23.             }  
  24.             catch (BeanDefinitionStoreException ex) {  
  25.                 parserContext.getReaderContext().error(ex.getMessage(), element);  
  26.                 return null;  
  27.             }  
  28.         }  
  29.         return definition;  
  30.     }  
 

   注意其中這樣一行:

 

Java代碼  
  1. AbstractBeanDefinition definition = parseInternal(element, parserContext);  

    這個parseInternal是在TxAdviceBeanDefinitionParser的父類AbstractSingleBeanDefinitionParser中實現(xiàn)的,代碼如下:

 

Java代碼  
  1. @Override  
  2.     protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {  
  3.         BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();  
  4.         String parentName = getParentName(element);  
  5.         if (parentName != null) {  
  6.             builder.getRawBeanDefinition().setParentName(parentName);  
  7.         }  
  8.         Class beanClass = getBeanClass(element);  
  9.         if (beanClass != null) {  
  10.             builder.getRawBeanDefinition().setBeanClass(beanClass);  
  11.         }  
  12.         else {  
  13.             String beanClassName = getBeanClassName(element);  
  14.             if (beanClassName != null) {  
  15.                 builder.getRawBeanDefinition().setBeanClassName(beanClassName);  
  16.             }  
  17.         }  
  18.         builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));  
  19.         if (parserContext.isNested()) {  
  20.             // Inner bean definition must receive same scope as containing bean.  
  21.             builder.setScope(parserContext.getContainingBeanDefinition().getScope());  
  22.         }  
  23.         if (parserContext.isDefaultLazyInit()) {  
  24.             // Default-lazy-init applies to custom bean definitions as well.  
  25.             builder.setLazyInit(true);  
  26.         }  
  27.         doParse(element, parserContext, builder);  
  28.         return builder.getBeanDefinition();  
  29.     }  

    其中有一行:

 

Java代碼  
  1. Class beanClass = getBeanClass(element);  

   getBeanClass是在TxAdviceBeanDefinitionParser中實現(xiàn)的,很簡單:

 

Java代碼  
  1. @Override  
  2.     protected Class getBeanClass(Element element) {  
  3.         return TransactionInterceptor.class;  
  4.     }  

  至此,這個標簽解析的流程已經(jīng)基本清晰了。那就是:解析除了一個以TransactionInerceptor為classname的beandefinition并且注冊這個bean。剩下來要看的,就是這個TranscationInterceptor到底是什么?

 看看這個類的接口定義,就明白了:

 

Java代碼  
  1. public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable  

  這根本就是一個spring AOP的advice嘛!現(xiàn)在明白為什么事務(wù)的配置能通過aop產(chǎn)生作用了吧?

  下面具體看看這個advice的advice:

 

Java代碼  
  1. public Object invoke(final MethodInvocation invocation) throws Throwable {  
  2.         // Work out the target class: may be <code>null</code>.  
  3.         // The TransactionAttributeSource should be passed the target class  
  4.         // as well as the method, which may be from an interface.  
  5.         Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null);  
  6.   
  7.         // If the transaction attribute is null, the method is non-transactional.  
  8.         final TransactionAttribute txAttr =  
  9.                 getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);  
  10.         final PlatformTransactionManager tm = determineTransactionManager(txAttr);  
  11.         final String joinpointIdentification = methodIdentification(invocation.getMethod());  
  12.   
  13.         if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {  
  14.             // Standard transaction demarcation with getTransaction and commit/rollback calls.  
  15.             TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);  
  16.             Object retVal = null;  
  17.             try {  
  18.                 // This is an around advice: Invoke the next interceptor in the chain.  
  19.                 // This will normally result in a target object being invoked.  
  20.                 retVal = invocation.proceed();  
  21.             }  
  22.             catch (Throwable ex) {  
  23.                 // target invocation exception  
  24.                 completeTransactionAfterThrowing(txInfo, ex);  
  25.                 throw ex;  
  26.             }  
  27.             finally {  
  28.                 cleanupTransactionInfo(txInfo);  
  29.             }  
  30.             commitTransactionAfterReturning(txInfo);  
  31.             return retVal;  
  32.         }  
  33.   
  34.         else {  
  35.             // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.  
  36.             try {  
  37.                 Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,  
  38.                         new TransactionCallback<Object>() {  
  39.                             public Object doInTransaction(TransactionStatus status) {  
  40.                                 TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);  
  41.                                 try {  
  42.                                     return invocation.proceed();  
  43.                                 }  
  44.                                 catch (Throwable ex) {  
  45.                                     if (txAttr.rollbackOn(ex)) {  
  46.                                         // A RuntimeException: will lead to a rollback.  
  47.                                         if (ex instanceof RuntimeException) {  
  48.                                             throw (RuntimeException) ex;  
  49.                                         }  
  50.                                         else {  
  51.                                             throw new ThrowableHolderException(ex);  
  52.                                         }  
  53.                                     }  
  54.                                     else {  
  55.                                         // A normal return value: will lead to a commit.  
  56.                                         return new ThrowableHolder(ex);  
  57.                                     }  
  58.                                 }  
  59.                                 finally {  
  60.                                     cleanupTransactionInfo(txInfo);  
  61.                                 }  
  62.                             }  
  63.                         });  
  64.   
  65.                 // Check result: It might indicate a Throwable to rethrow.  
  66.                 if (result instanceof ThrowableHolder) {  
  67.                     throw ((ThrowableHolder) result).getThrowable();  
  68.                 }  
  69.                 else {  
  70.                     return result;  
  71.                 }  
  72.             }  
  73.             catch (ThrowableHolderException ex) {  
  74.                 throw ex.getCause();  
  75.             }  
  76.         }  
  77.     }  
 

   哦,原來就是在這里控制了method invocation(spring aop是基于method的)!根據(jù)我們的配置,來決定

  是不是對method使用事務(wù)。

 

   至此,spring的事務(wù)管理已經(jīng)基本清晰了。就是解析出一個advice bean(of class : TransactionInterceptor)來,

   然后在aop中配置pointcut和這個advice,就能產(chǎn)生作用了!

 

   當然,這里沒有分析事物控制的細節(jié)以及spring aop的原理,這些在接下來的章節(jié)里面會慢慢補全~

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
編程語言Spring 源碼閱讀-2-自定義標簽簡單使用與解析
Spring 事務(wù)介紹
面試官:@Transactional 注解是如何實現(xiàn)的?面試必問!
源代碼解讀Spring只讀事務(wù)與讀寫事務(wù)的性能的差別
Spring源代碼解析(六):Spring聲明式事務(wù)處理
請不要再使用低級別的AOP API
更多類似文章 >>
生活服務(wù)
分享 收藏 導長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服