日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

源代碼解讀Spring只讀事務(wù)與讀寫事務(wù)的性能的差別

 燮羽 2010-12-09
前言:
  如果大家使用過Spring事務(wù)管理,會發(fā)現(xiàn)Spring提供的事務(wù)分為“只讀”和“讀寫”事務(wù)兩類。這不免就會疑問這兩種事務(wù)會有什么不同?本文則通過對Spring和Hibernate源代碼的剖析來找出這兩種事務(wù)的區(qū)別。特別是運行性能方面的區(qū)別。
  解讀的源代碼版本為 Spring 2.5.6.SEC01 ,Hibernate 3.3.2.GA。

  Spring對事務(wù)的支持也分編程式和聲明式,本文以基于Annotation方式的聲明式事務(wù)為例:
 
  Spring的配置如下:
    <bean
        
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
        
<property name="proxyTargetClass" value="true"></property>
    
</bean>
    
<bean id="entityManagerFactory"
        class
="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        
<property name="persistenceUnitName" value="entityManager" />
        
<property name="jpaProperties">
            
<props>
            
</props>
        
</property>
    
</bean>

    
<bean id="transactionManager"
        class
="org.springframework.orm.jpa.JpaTransactionManager">
        
<property name="entityManagerFactory" ref="entityManagerFactory" />
    
</bean>
    
<bean id="transactionInterceptor"
        class
="org.springframework.transaction.interceptor.TransactionInterceptor">
        
<property name="transactionManager" ref="transactionManager" />
        
<property name="transactionAttributeSource">
            
<bean
                
class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource" />
        
</property>
    
</bean>
    
<bean id="transactionAttributeSourceAdvisor"
        class
="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
        
<property name="transactionInterceptor"    ref="transactionInterceptor" />
    
</bean>

從配置中,可以看到事務(wù)的攔截,都由 TransactionInterceptor 類進行處理
下面是invoke方法的核心處理過程:

    public Object invoke(final MethodInvocation invocation) throws Throwable {
        
// Work out the target class: may be <code>null</code>.
        
// The TransactionAttributeSource should be passed the target class
        
// as well as the method, which may be from an interface.
        Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null);

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

        
if (txAttr == null || !(getTransactionManager() instanceof CallbackPreferringPlatformTransactionManager)) {
            
// Standard transaction demarcation with getTransaction and commit/rollback calls.
            TransactionInfo txInfo = createTransactionIfNecessary(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.proceed();
            }
            
catch (Throwable ex) {
                
// target invocation exception
                completeTransactionAfterThrowing(txInfo, ex);
                
throw ex;
            }
            
finally {
                cleanupTransactionInfo(txInfo);
            }
            
//處理事務(wù)的操作
            commitTransactionAfterReturning(txInfo);
            
return retVal;
        }
        .省略
    }

針對事務(wù)的操作,就是調(diào)用 commitTransactionAfterReturning 方法進行事務(wù)的處理。
該方法會調(diào)用AbstractPlatformTransactionManager類的commit和processCommit方法。processCommit方法是真正調(diào)用Hibernate事務(wù)處理的實現(xiàn)。

    private void processCommit(DefaultTransactionStatus status) throws TransactionException {
        
try {
            
boolean beforeCompletionInvoked = false;
            
try {
                prepareForCommit(status);
                triggerBeforeCommit(status);
                triggerBeforeCompletion(status);
                beforeCompletionInvoked 
= true;
                
boolean globalRollbackOnly = false;
                
if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
                    globalRollbackOnly 
= status.isGlobalRollbackOnly();
                }
                
if (status.hasSavepoint()) {
                    
if (status.isDebug()) {
                        logger.debug(
"Releasing transaction savepoint");
                    }
                    status.releaseHeldSavepoint();
                }
                
else if (status.isNewTransaction()) { //如果是一個新啟的事務(wù)
                    if (status.isDebug()) {
                        logger.debug(
"Initiating transaction commit");
                    }
//則進行事務(wù)的提交處理
                    doCommit(status);
                }
             代碼省略
    }

doCommit 方法的調(diào)用 會觸發(fā) Hibernate的JDBCTransaction的commit方法調(diào)用

    public void commit() throws HibernateException {
        
if (!begun) {
            
throw new TransactionException("Transaction not successfully started");
        }

        log.debug(
"commit");
        
//如果是只讀事務(wù),Spring會將transactionContext的 isFlushModeNever 設(shè)置為true
        if ( !transactionContext.isFlushModeNever() && callback ) {
          
//刷新一級緩存中的持久對象,向數(shù)據(jù)庫發(fā)送sql語句  
            transactionContext.managedFlush(); //if an exception occurs during flush, user must call rollback()
        }

        notifyLocalSynchsBeforeTransactionCompletion();
        
if ( callback ) {
            jdbcContext.beforeTransactionCompletion( 
this );
        }

        
try {
            commitAndResetAutoCommit();
            log.debug(
"committed JDBC Connection");
            committed 
= true;
            
if ( callback ) {
                jdbcContext.afterTransactionCompletion( 
truethis );
            }
            notifyLocalSynchsAfterTransactionCompletion( Status.STATUS_COMMITTED );
        }
        
catch (SQLException e) {
            log.error(
"JDBC commit failed", e);
            commitFailed 
= true;
            
if ( callback ) {
                jdbcContext.afterTransactionCompletion( 
falsethis );
            }
            notifyLocalSynchsAfterTransactionCompletion( Status.STATUS_UNKNOWN );
            
throw new TransactionException("JDBC commit failed", e);
        }
        
finally {
            closeIfRequired();
        }
    }   

關(guān)鍵點已經(jīng)在上面的注釋中說明。
當(dāng)事務(wù)被標(biāo)識為只讀事務(wù)時,Spring可以對某些可以針對只讀事務(wù)進行優(yōu)化的資源就可以執(zhí)行相應(yīng)的優(yōu)化措施,上面Spring告之hibernate的session在只讀事務(wù)模式下不用嘗試檢測和同步持久對象的狀態(tài)的更新。


總結(jié):
  如果在使用事務(wù)的情況下,所有操作都是讀操作,那建議把事務(wù)設(shè)置成只讀事務(wù),或者事務(wù)的傳播途徑最好能設(shè)置為 supports (運行在當(dāng)前的事務(wù)范圍內(nèi),如果當(dāng)前沒有啟動事務(wù),那么就不在事務(wù)范圍內(nèi)運行)或者 not supports (不在事務(wù)范圍內(nèi)執(zhí)行,如果當(dāng)前啟動了事務(wù),那么掛起當(dāng)前事務(wù)),這樣不在事務(wù)下,就不會調(diào)用transactionContext.managedFlush(); 方法。
所有只讀事務(wù)與讀寫事務(wù)的比較大的運行性能區(qū)別就是只讀事務(wù)避免了Hibernate的檢測和同步持久對象的狀態(tài)的更新,提升了運行性能。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多