动态代理没有明确指定scala中的类型

时间:2010-10-10 15:32:12

标签: scala dynamic proxy

是否可以使用一个方法来获取任意实例并返回一个与原始参数具有相同类型的java.reflection.Proxy或类似文件?

我想它看起来应该是这样的:

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

或者

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

其中T是S的子类型,它是由所有已实现接口的组合产生的,因为它似乎不能代理实际的类,而只是接口。

2 个答案:

答案 0 :(得分:3)

我认为以下应该可以解决问题。请注意,它不能返回S,因为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:_*)
    }
  })
}

答案 1 :(得分:2)

在您想使用单一界面代理对象的情况下,您可以执行以下操作(基于Hiram 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引入基于蛋糕模式的代码库。