是否有Scala方式用于代理类的运行时生成?不是DynamicProxy
,而是扩展提供类/接口的运行时类型,并通过提供的回调传递所有调用。
Java世界使用cglib / javassist,但在Scala中代理的最佳方式是什么?
def makeProxy[T](interceptor: Interceptor, implicit baseClass: Manifest[T]): T
谷歌称Scala宏可以用于此,但我不确定如何。
答案 0 :(得分:2)
这是一个如何(更多)用宏来做这样的事情的例子:
def testImpl[T : c.WeakTypeTag](c: Context): c.Expr[Any] = {
import c.universe._
val className = newTypeName(weakTypeTag[T].tpe.typeSymbol.name.toString) //not best way
val m = weakTypeOf[T].declarations.iterator.toList.map(_.asMethod) //`declaration` takes only current; `members` also takes inherited
.filter(m => !m.isConstructor && !m.isFinal).map { m => //all reflection info about method
q"""override def ${m.name} = 9""" //generating new method
}
c.Expr { q"""new $className { ..$m } """}
}
def t[T] = macro testImpl[T]
class Aaa{ def a = 7; def b = 8}
scala> t[Aaa].a
res39: Int = 9
scala> t[Aaa].b
res40: Int = 9
所有这样的宏只有在覆盖方法不是最终的时才起作用,因为它们不能改变类型(因为它在编译时工作) - 只创建新的和继承。此示例不使用非空构造函数和许多其他内容处理类。 m
这里是MethodSymbol
的实例,并为您提供有关输入类的全部scala风格反映'方法。您只需在响应中生成正确的AST。
要了解更多信息:
另一种解决方案是:
scala> def getClasss[T: ClassTag] = classTag[T].runtimeClass
getClasss: [T](implicit evidence$1: scala.reflect.ClassTag[T])Class[_]
使用此实例,您可以应用任何asm / cglib / javassist甚至DynamicProxy
。