动态代理,无需在 scala 中显式指定类型

发布于 2024-09-27 00:33:08 字数 369 浏览 3 评论 0原文

是否有可能有一个方法接受任意实例并返回 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 的子类型,它是由所有已实现的接口组合而成的,因为我似乎无法代理实际的类,而只能代理接口。

is it possible to have a method that takes an arbitrary instance and returns a java.reflection.Proxy or similar that has the same type as the original argument?

I guess it should look something like this:

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

or this

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

where T is the subtype of S which results from a combination of all the implemented interfaces, since it doesn't seem like I can Proxy an actual class, but only interfaces.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

饭团 2024-10-04 00:33:08

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

I think the following should do the trick. Note that it can't return an S since it's likely S is not an interface.

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:_*)
    }
  })
}
绮烟 2024-10-04 00:33:08

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

In the situations when you want to proxy an object using single interface you can do something like this (based on Hiram Chirino answer):

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

And having an interface SessionSvc use it like this:

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

This way I managed to introduce rather painless AOP into cake pattern based codebase.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文