2010-10-10 74 views
5

是否有可能擁有一個接受任意實例並返回一個與原始參數具有相同類型的java.reflection.Proxy或類似方法?動態代理沒有在scala中明確指定類型

我猜應該是這個樣子:

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

或本

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

其中T是S的從所有實現的接口的組合產生的亞型,因爲它不看起來我可以代理一個實際的類,但只有接口。

+0

有點舊但尚未...代理可以轉換爲接口而不是具體的類 – ozma 2017-05-02 17:03:11

回答

3

我認爲以下應該做的伎倆。請注意,它不能返回S,因爲它可能不是一個接口。

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

結果類型是Object,因此它不能解決我的問題。看起來我不能擁有我想要的東西,所以我會接受這個答案。 – 2011-02-14 08:04:14

2

在情況下,當你使用單一的界面,你可以做這樣的事情(基於希蘭Chirino回答)要代理的對象:

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] 
} 

而且具有界面SessionSvc使用它像這樣:

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

這樣,我成功地引進,而無痛AOP成米餅模式的代碼庫。