shj*_*shj 6 java reflection spring scala scala-2.9
我正在使用Scala 2.9.1
我已经定义了一个Logging特性:
trait Logging {
def debug(msg: String, throwables: Throwable*) = ....
....
}
Run Code Online (Sandbox Code Playgroud)
我有一个JMSPublisher类混合了Logging特性:
class JMSPublisher extends Publisher with Logging {
def publishProducts(list: List[_ <: Product]) = ....
def publish(list: Seq[Product]) = ....
}
Run Code Online (Sandbox Code Playgroud)
这一切都很好.我的问题是我有一个用户想要将我的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.......
Run Code Online (Sandbox Code Playgroud)
这段代码在Scala-2.8下运行,我听说Scala标记的特性有一些方法,如2.9中所述.我认为这是导致Spring失败的原因.如果我的类无法被Spring加载,我无法升级到Scala-2.9.
有没有人遇到过这个问题?有任何修复或解决方法吗?
我们看到了同样的事情。我从来没有弄清楚 Scala 2.9.x 中的哪些变化引发了这个问题,但我认为真正的问题在于 Spring 本身。
当您将特征混合到类中时,会在类中添加合成方法,在字节代码中标记为桥接方法,然后转发到特征中方法的实现。
当子类重写超类或接口中的方法时,Java 还会向类添加桥接方法,但会细化返回类型。由于返回类型是字节码级别方法签名的一部分,因此需要一个转发方法,以便只知道父方法签名的客户端仍然可以调用子类中的方法。(更多详细信息:Method.isBridge 用于什么?)
Spring 检查字节码中的桥接方法,其原因在文章A Bridge Too Far中描述。那篇文章的名字很讽刺——Spring 称其为“Spring 解决 Java 开发人员面临的硬基础设施问题并将其集成到应用程序堆栈中的完美示例”,但它对字节码的来源做了太多假设,并且更糟糕的是,无法禁用。
短期解决方法是避免将特征混合到您在 Spring 中使用的类中。您应该向 Spring 提交一个错误,以允许您禁用对非 Java 字节码的检查。