2011-11-04 16 views
6

estoy usando Scala 2.9.1Scala 2.9 Puente-Método

He definido un rasgo de registro como tal:

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

Y tengo una clase JMSPublisher que se mezcla en el rasgo de registro :

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

Todo esto compila bien. Mi problema es que tengo un usuario que quiere cargar mi JMSPublisher en Spring. Él está usando Spring 2.5.6.

Cuando ApplicationContext se carga durante el inicio, la aplicación se bloquea con una IllegalStateException, quejándose de que no puede encontrar un método de puente relacionado con mi rasgo de registro.

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

Este código trabajó bajo Scala-2.8, y oí que Scala está marcando rasgo que tienen algunos métodos como puente en 2,9. Creo que esto es lo que está causando que Spring falle. No puedo actualizar a Scala-2.9 si mi clase no puede ser cargada por Spring.

¿Alguien se ha encontrado con este problema? ¿Hay alguna solución o solución alternativa?

+0

Creo que estamos obteniendo algo similar, afortunadamente no afecta nuestra aplicación actual, solo Spring IDE que marca algunos beans con errores, ya que se queja de que algunos de los métodos definidos por los rasgos no existen. – Nick

+1

Vea esto: http://stackoverflow.com/questions/8748625/why-are-concrete-function-implementations-in-traits-compiled-to-bridge-methods-i – Janx

Respuesta

3

Vimos lo mismo. Nunca me di cuenta de qué cambio en Scala 2.9.x desencadenó esto, pero creo que el verdadero problema es con Spring.

Cuando mezcla un rasgo en una clase, agrega métodos sintéticos a en la clase, marcados en el código de bytes como métodos de puente, que se envían a la implementación del método en el rasgo.

Java también agrega métodos de puente a las clases, cuando una subclase anula un método en una superclase o interfaz, pero refina el tipo de retorno. Debido a que el tipo de devolución es parte de la firma del método en el nivel de bytecode, se necesita un método de reenvío para que los clientes que solo conocen la firma del método primario puedan llamar al método en la subclase. (Más detalles: what java.lang.reflect.Method.isBridge() used for?)

Spring inspecciona el bytecode para los métodos de puente por los motivos descritos en el artículo A Bridge Too Far. El nombre de ese artículo es irónico: Spring lo llama "un ejemplo perfecto de Spring resolviendo los problemas de infraestructura que enfrentan los desarrolladores de Java e integrándolos en la pila de aplicaciones", pero hace demasiadas suposiciones sobre el origen del bytecode, y peor, no se puede deshabilitar.

Solución temporal a corto plazo, es evitar mezclar rasgos en las clases que utiliza en Spring. Debe presentar un error con Spring para permitirle desactivar esta comprobación para bytecode que no sea Java.

Cuestiones relacionadas