代理类支持

时间:2015-05-05 18:35:17

标签: scala

是否有Scala方式用于代理类的运行时生成?不是DynamicProxy,而是扩展提供类/接口的运行时类型,并通过提供的回调传递所有调用。

Java世界使用cglib / javassist,但在Scala中代理的最佳方式是什么?

def makeProxy[T](interceptor: Interceptor, implicit baseClass: Manifest[T]): T

谷歌称Scala宏可以用于此,但我不确定如何。

1 个答案:

答案 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