我正在使用Scala 2.9.1
我已经定义了一个Logging特性:
trait Logging {
def debug(msg: String,throwables: Throwable*) = ....
....
}
我有一个JMSPublisher类混合了Logging特性:
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.
有没有人遇到过这个问题?有任何修复或解决方法吗?
最佳答案
我们看到了同样的事情.我从未弄清楚Scala 2.9.x中的哪些变化触发了这一点,但我认为真正的问题在于Spring本身.
将特征混合到类中时,在类中添加合成方法,在字节代码中标记为桥接方法,然后转发到特征中方法的实现.
当子类覆盖超类或接口中的方法时,Java还会向类添加桥接方法,但会优化返回类型.因为返回类型是字节码级别的方法签名的一部分,所以需要转发方法,以便只知道父方法签名的客户端仍然可以调用子类中的方法. (更多细节:what java.lang.reflect.Method.isBridge () used for?)
Spring出于第A Bridge Too Far条所述的原因检查了桥接方法的字节码.该文章的名称具有讽刺意味 – Spring称之为“Spring解决Java开发人员面临的硬件基础架构问题并将其集成到应用程序堆栈中的完美示例”,但它对字节码的来源做了太多假设,更糟糕的是,无法禁用.
短期解决方法是避免将特征混合到您在Spring中使用的类中.您应该向Spring提出一个错误,允许您禁用对非Java字节码的此检查.