2010-10-10 10 views
5

¿es posible tener un método que toma una instancia arbitraria y devuelve un java.reflection.Proxy o similar que tiene el mismo tipo que el argumento original?Proxy dinámico sin especificar explícitamente el tipo en scala

supongo que debe ser algo como esto:

def createProxy[S](model: S)(implicit manifest: Manifest[S]): S = {...} 

o esta

def createProxy[S, T<:S](model: S)(implicit manifest: Manifest[S]): T = {...} 

donde T es el subtipo de S, que resulta de una combinación de todas las interfaces implementadas, ya que doesn Parece que puedo Proxy una clase real, pero solo interfaces.

+0

un poco viejo pero aún ... el proxy solo se puede convertir en interfaz, no en una clase concreta – ozma

Respuesta

3

Creo que lo siguiente debería hacer el truco. Tenga en cuenta que no puede devolver una S ya que es probable que S no sea una interfaz.

import java.lang.reflect._ 

def createProxy[S](model: S)(implicit manifest: Manifest[S]) = { 
    val clazz = manifest.erasure 
    Proxy.newProxyInstance(clazz.getClassLoader, clazz.getInterfaces, new InvocationHandler() { 
    def invoke(proxy:Object, method:Method, args:scala.Array[Object]) = { 
     method.invoke(model, args:_*) 
    } 
    }) 
} 
+0

El tipo de resultado es Object, por lo que no resuelve mi problema. Parece que no puedo tener lo que quiero, así que aceptaré esta respuesta. –

2

En las situaciones en las que desea proxy de un objeto utilizando una única interfaz que puede hacer algo como esto (en base a Hiram Chirino respuesta):

import java.lang.reflect.{Method, InvocationHandler, Proxy} 

def createProxy[I](proxee: I, interfaceClass: Class[I]): I = { 
    assert(interfaceClass.isInterface, "interfaceClass should be an inteface class") 
    Proxy.newProxyInstance(interfaceClass.getClassLoader, Array(interfaceClass), new InvocationHandler() { 
    override def invoke(proxy: Object, method: Method, args: Array[Object]) = { 
     println("before") 
     val result = method.invoke(proxee, args: _*) 
     println("after") 
     result 
    } 
    }).asInstanceOf[I] 
} 

Y tener una interfaz SessionSvc utilizar de esta manera :

val sessionSvc = createProxy(new SessionSvcMongo, classOf[SessionSvc]) 

de esta manera me las arreglé para introducir más indolora AOP en base de código basada patrón de la torta.

Cuestiones relacionadas