代码之家  ›  专栏  ›  技术社区  ›  Jens Schauder

在scala中不明确指定类型的动态代理

  •  5
  • Jens Schauder  · 技术社区  · 15 年前

    有没有可能有一个方法接受一个任意实例并返回一个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 回复  |  直到 15 年前
        1
  •  3
  •   Hiram Chirino    15 年前

    我认为下面这句话应该有用。注意,它不能返回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:_*)
        }
      })
    }
    
        2
  •  2
  •   Tvaroh    12 年前

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