Scala 2.9 桥接方法

发布于 2024-12-13 15:39:30 字数 1162 浏览 6 评论 0原文

我正在使用 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。

有人遇到过这个问题吗?有任何修复或解决方法吗?

I'm using Scala 2.9.1

I've defined a Logging trait as such:

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

And I have a JMSPublisher class which mixes-in the Logging trait:

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

This all compiles fine. My issue is that I have a user who wants to load my JMSPublisher into Spring. He's using Spring 2.5.6.

When the ApplicationContext is loaded during startup, the app crashes with an IllegalStateException, complaining that it can't find a bridged-method related to my Logging trait.

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.......

This code worked under Scala-2.8, and I heard that Scala is marking trait that have some methods as bridged in 2.9. I think this is what is causing Spring to fail. I can't upgrade to Scala-2.9 if my class can't be loaded by Spring.

Has anyone run into this issue? Is there any fix or work-around?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

扛起拖把扫天下 2024-12-20 15:39:30

我们看到了同样的事情。我从来没有弄清楚 Scala 2.9.x 中的哪些变化引发了这个问题,但我认为真正的问题在于 Spring 本身。

当您将特征混合到类中时,会在类中添加合成方法,在字节代码中标记为桥接方法,这些方法将转发到特征中方法的实现。

当子类重写超类或接口中的方法时,Java 还会向类添加桥接方法,但会细化返回类型。由于返回类型是字节码级别方法签名的一部分,因此需要一个转发方法,以便只知道父方法签名的客户端仍然可以调用子类中的方法。 (更多详细信息:Method.isBridge 用于什么?

Spring 检查桥接方法的字节码,其原因在文章 一座太远的桥。那篇文章的名字很讽刺——Spring 称其为“Spring 解决 Java 开发人员面临的硬基础设施问题并将其集成到应用程序堆栈中的完美示例”,但它对字节码的来源做了太多假设,并且更糟糕的是,无法禁用。

短期解决方法是避免将特征混合到您在 Spring 中使用的类中。您应该向 Spring 提交一个错误,以允许您禁用对非 Java 字节码的检查。

We saw the same thing. I never figured out what change in Scala 2.9.x triggered this, but I think the real problem is with Spring itself.

When you mix a trait into a class, the adds synthetic methods to in the class, marked in the byte code as bridge methods, that forward to the implementation of the method in the trait.

Java also adds bridge methods to classes, when a sub-class overrides a method in a superclass or interface, but refines the return type. Because the return type is part of the method signature at the bytecode level, a forwarding method is needed so that clients who only know about the parent method signature can still call the method in the subclass. (More details: What Method.isBridge used for?)

Spring inspects the bytecode for bridge methods for reasons described in the article A Bridge Too Far. The name of that article is ironic -- Spring calls this "a perfect example of Spring solving the hard infrastructure problems that Java developers face and integrating them into the application stack", but it makes too many assumptions about the source of the bytecode, and worse, can't be disabled.

Short term workaround, is to avoid mixing traits into classes you use in Spring. You should lodge a bug with Spring to allow you to disable this check for non-Java bytecode.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文