如何使用reflect来获取scala 2.11中的注释实例

时间:2015-02-21 14:08:29

标签: scala reflection

我希望通过反射得到注释实例,我尝试使用此方法link但它不起作用。

当注释字段类型是基本且没有默认值时会成功,但是当类型很复杂或具有默认值时,它将失败。

在我的代码中:

import org.scalatest.FunSuite

import scala.annotation.StaticAnnotation
import scala.reflect.runtime.universe._

object ReflectHelper {

  val runtime = runtimeMirror(getClass.getClassLoader)

  /**
   * @param beanClazz target bean class
   * @tparam A target annotation
   * @return  annotation instances
   */
  def getClassAnnotation[A: TypeTag](beanClazz: Class[_]): Option[A] = {
    val typeAnnotation = typeOf[A]
    scala.reflect.runtime.currentMirror.classSymbol(beanClazz).toType.typeSymbol.asClass.annotations.find(a => a.tree.tpe == typeAnnotation).map {
      annotation =>
        /*
         *  Has error : scala.reflect.internal.Trees$Select cannot be cast to scala.reflect.api.Constants$ConstantApi
         *  when annotation field use default value
         *
         *  Has error : scala.reflect.internal.Trees$TypeApply cannot be cast to scala.reflect.api.Constants$ConstantApi
         *  when annotation field  type is collection
         */
        val value = annotation.tree.children.tail.map(_.productElement(0).asInstanceOf[Constant].value)
        runtime.reflectClass(typeAnnotation.typeSymbol.asClass).
          reflectConstructor(typeAnnotation.decl(termNames.CONSTRUCTOR).asMethod)(value: _*).
          asInstanceOf[A]
    }
  }

}

case class Entity1(idField: String = "id") extends StaticAnnotation

case class Entity2(rels: List[String] = List()) extends StaticAnnotation

@Entity1(idField = "pk")
case class Test1Entity()

@Entity1()
case class Test2Entity()

@Entity2(rels = List("fieldA"))
case class Test3Entity()

class Test extends FunSuite {
  test("Bean Test") {
    //Success
    assert(ReflectHelper.getClassAnnotation[Entity1](classOf[Test1Entity]).get.idField == "pk")
    //Error : scala.reflect.internal.Trees$Select cannot be cast to scala.reflect.api.Constants$ConstantApi
    assert(ReflectHelper.getClassAnnotation[Entity1](classOf[Test2Entity]).get.idField == "id")
    //Error : scala.reflect.internal.Trees$TypeApply cannot be cast to scala.reflect.api.Constants$ConstantApi
    assert(ReflectHelper.getClassAnnotation[Entity2](classOf[Test3Entity]).get.rels(0) == "fieldA")
  }
}

感谢。

0 个答案:

没有答案