1. gzyueqian
      18529173453
      首頁 > 新聞中心 > > 正文

      Spring2.0rc3的一個Bug

      更新時間: 2007-05-16 13:37:22來源: 粵嵌教育瀏覽量:882


        在使用Spring自動代理配置事務時,要配置TransactionAttributeSourceAdvisor(自動代理只能用于Advisor),該類需要一個事務攔截器(TransactionInterceptor)的引用。TransactionAttributeSourceAdvisor類提供了兩種方式注入TransactionInterceptor對象,一種是通過構造器注入,一種是通過setter注入。當采用構造器注入時,運行良好;當采用setter注入時,則會拋出下列異常:

      org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionAttributeSourceAdvisor' defined in class path resource [beans.xml]: Instantiation of bean failed; nested exception is java.lang.NullPointerException

      Caused by: java.lang.NullPointerException

      at org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor$TransactionAttributeSourcePointcut.getTransactionAttributeSource(TransactionAttributeSourceAdvisor.java:102)

      at org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor$TransactionAttributeSourcePointcut.hashCode(TransactionAttributeSourceAdvisor.java:121)

      at java.lang.Object.toString(Object.java:209)

      at java.lang.String.valueOf(String.java:2577)



      錯誤原因

        在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory抽象類中,createBean()方法負責創建Bean。在該方法中有下列一段代碼:



      bean = instanceWrapper.getWrappedInstance();



      // Eagerly cache singletons to be able to resolve circular references

      // even when triggered by lifecycle interfaces like BeanFactoryAware.

      if (isAllowCircularReferences() && isSingletonCurrentlyInCreation(beanName)) {

      if (logger.isDebugEnabled()) {

      logger.debug("Eagerly caching bean [" + bean + "] with name '" + beanName +

      "' to allow for resolving potential circular references");

      }



        也就是在Bean創建成功后,并且配置的日志級別是DEBUG,那么打印緩存的bean信息。而問題也就出在這個日志記錄代碼中。

        TransactionAttributeSourceAdvisor類繼承自AbstractPointcutAdvisor,在這個父類中,重寫了toString()方法,在上述日志輸出語句中,打印bean對象(類型為TransactionAttributeSourceAdvisor),就會調用其繼承的toString()方法,該方法如下:

      public String toString() {

      return "PointcutAdvisor: pointcut [" + getPointcut() + "], advice [" + getAdvice() + "]";

      //return "PointcutAdvisor: pointcut [], advice [" + getAdvice() + "]";

      }

      在這個代碼中又調用了getPointcut()方法,TransactionAttributeSourceAdvisor類的該方法如下:

      public Pointcut getPointcut() {

      return this.pointcut;

      }

      成員變量pointcut的類型定義如下:

      private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut();

        在toString()方法中構造字符串時,如果有對象類型,就會調用其toString()方法,在這里,也就會調用TransactionAttributeSourcePointcut的toString()方法,該類是TransactionAttributeSourceAdvisor中的一個內部類,本身沒有定義toString()方法,于是就會調用Object類中的toString()方法。Object類中的toString()方法如下:

      java.lang.Object

      public String toString() {

      return getClass().getName() + "@" + Integer.toHexString(hashCode());

      }

        Object類的toString()方法打印類名和對象的HashCode,問題就出在hashCode()的調用上,內部類TransactionAttributeSourcePointcut雖然沒有重寫toString()方法,但是重寫了hashCode()方法。該方法如下:

      public int hashCode() {

      TransactionAttributeSource tas = getTransactionAttributeSource();

      return (tas != null ? tas.hashCode() : 0);

      }

        在這個方法中,它去計算TransactionAttributeSource對象的hashCode,因此要調用getTransactionAttributeSource(),該方法是TransactionAttributeSourcePointcut中的方法,該方法如下:

      private TransactionAttributeSource getTransactionAttributeSource() {

      return transactionInterceptor.getTransactionAttributeSource();

      }

        由于采用了Setter注入,而此時調用藍色顯示的代碼時,Bean對象剛構造完成,屬性還未設置,也就是說,TransactionAttributeSourceAdvisor類的攔截器還未注入,其成員變量transactionInterceptor為null。因此拋出空指針異常。

        解決辦法有兩個:1、采用構造器注入;2、設置日志級別高于DEBUG。

        但這不是根本的解決辦法,在7月10日的“Java企業級開發班”上課時,我曾經對學員說,要修正這個問題實際上非常簡單,只需要TransactionAttributeSourcePointcut類的getTransactionAttributeSource()方法中對transactionInterceptor做一個是否為null的判斷,如果為null,就返回null,如果不為null,就返回transactionInterceptor.getTransactionAttributeSource()。

        后記:今天在弄事務時又想到了這個問題,于是上Spring的網站上下了一個RC4版本,欣喜的發現,Spring的開發團隊已經修正了這個錯誤,TransactionAttributeSourcePointcut類的getTransactionAttributeSource()方法改為如下:

      private TransactionAttributeSource getTransactionAttributeSource() {

      return (transactionInterceptor != null ? transactionInterceptor.getTransactionAttributeSource() : null);

      }

      和我當初設想的一致。

      免費預約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 亚洲欧美中文日韩v在线观看不卡 | 亚洲乱码中文字幕综合69堂 | 欧美性爱专区在线观看 | 亚洲欧美日韩在线观看 | 日本三级香港三级人妇99视频 | 亚洲V国产一区二区三区 |