2011-11-04 30 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字节码的检查。