2011-11-04 53 views
6

我使用Scala的2.9.1斯卡拉2.9橋法

我的測井特徵這樣:

trait Logging { 
    def debug(msg: String, throwables: Throwable*) = .... 
    .... 
} 

而且我有一個JMSPublisher類混合,在記錄特質:

class JMSPublisher extends Publisher with Logging { 
    def publishProducts(list: List[_ <: Product]) = .... 
    def publish(list: Seq[Product]) = .... 
} 

這一切都編譯好。我的問題是我有一個用戶想要將我的JMSPublisher加載到Spring中。他使用Spring 2.5.6。

當ApplicationContext在啓動過程中被加載時,該應用程序崩潰並帶有IllegalStateException,抱怨說它無法找到與我的Logging特徵相關的橋接方法。

Initialization of bean failed; nested exception is java.lang.IllegalStateException: Unable to locate bridged method for bridge method 'public void com.app.messaging.JmsPublisher.debug(java.lang.String, scala.collection.Seq)' 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480) 
    .....stack trace follows....... 

此代碼在Scala-2.8下工作,我聽說Scala標記的特徵有一些在2.9中橋接的方法。我認爲這是導致Spring失敗的原因。如果我的類不能被Spring加載,我無法升級到Scala-2.9。

有沒有人遇到過這個問題?是否有任何修復或解決方法?

+0

我想我們得到了類似的東西 - 幸運的是它不影響我們的實際應用程序,只是Spring IDE標記了一些錯誤的bean,因爲它抱怨說某些特徵定義的方法不存在。 – Nick

+1

看到這個:http://stackoverflow.com/questions/8748625/why-are-concrete-function-implementations-in-traits-compiled-to-bridge-methods-i – Janx

回答

3

我們看到了同樣的事情。我從來沒有想到Scala 2.9.x會引發什麼變化,但我認爲真正的問題在於Spring本身。

當你將一個特徵混合到一個類中時,在該類中添加了合成方法,在字節代碼中標記爲橋接方法,即轉發到特徵中方法的實現。

當子類覆蓋超類或接口中的方法,但會優化返回類型時,Java還會將類橋添加到類中。由於返回類型是字節碼級別方法簽名的一部分,因此需要一種轉發方法,以便只知道父方法簽名的客戶端仍可以調用子類中的方法。 (更多詳細信息:what java.lang.reflect.Method.isBridge() used for?

由於文章A Bridge Too Far中描述的原因,Spring會檢查橋接方法的字節碼。該文章的名字具有諷刺意味 - Spring稱這是「Spring解決Java開發人員面臨的難題,並將它們整合到應用程序棧中的完美例子」,但它對字節碼的來源做了太多的假設,並且更糟的是,不能被禁用。

短期解決方法是避免將特徵混入您在Spring中使用的類中。您應該向Spring提交一個錯誤,以允許您禁用對非Java字節碼的檢查。