Scala 2.9 Bridge-метод

Я использую Скала 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. Я не могу перейти на Scala-2.9, если Spring не может загрузить мой класс.

Кто-нибудь сталкивался с этой проблемой? Есть ли какое-либо исправление или обходной путь?


person shj    schedule 04.11.2011    source источник
comment
Я думаю, что мы получаем что-то похожее — к счастью, это не влияет на наше приложение, а только на Spring IDE, который помечает некоторые bean-компоненты ошибками, поскольку жалуется, что некоторые методы, определяемые трейтами, не существуют.   -  person Nick    schedule 23.11.2011
comment
См. это: stackoverflow.com/questions/8748625/   -  person Janx    schedule 06.01.2012


Ответы (1)


Мы видели то же самое. Я так и не понял, какое изменение в Scala 2.9.x вызвало это, но я думаю, что настоящая проблема заключается в самом Spring.

Когда вы смешиваете трейт с классом, в класс добавляются синтетические методы, помеченные в байтовом коде как методы моста, которые направляют реализацию метода в трейте.

Java также добавляет промежуточные методы к классам, когда подкласс переопределяет метод в суперклассе или интерфейсе, но уточняет возвращаемый тип. Поскольку возвращаемый тип является частью сигнатуры метода на уровне байт-кода, необходим метод пересылки, чтобы клиенты, которые знают только сигнатуру родительского метода, могли вызывать метод в подклассе. (Подробнее: какой java.lang.reflect.Method.isBridge() используется для?)

Spring проверяет байт-код для методов моста по причинам, описанным в статье Мост слишком далеко. Название этой статьи иронично — Spring называет ее «прекрасным примером того, как Spring решает проблемы с жесткой инфраструктурой, с которыми сталкиваются разработчики Java, и интегрирует их в стек приложений», но в ней делается слишком много предположений об источнике байт-кода и хуже, не может быть отключен.

Краткосрочный обходной путь заключается в том, чтобы не смешивать черты с классами, которые вы используете в Spring. Вы должны зарегистрировать ошибку в Spring, чтобы вы могли отключить эту проверку для байт-кода, отличного от Java.

person retronym    schedule 06.11.2011