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

如何在scala 2.11中使用reflect获取注释实例,scala,reflection,Scala,Reflection,我希望通过反射获取注释实例,我尝试过使用此方法,但不起作用 当注释字段类型为基本且没有默认值时,它将成功,但当类型复杂或具有默认值时,它将失败 在我的代码中,例如: import org.scalatest.FunSuite import scala.annotation.StaticAnnotation import scala.reflect.runtime.universe._ object ReflectHelper { val runtime = runtimeMirror(

我希望通过反射获取注释实例,我尝试过使用此方法,但不起作用

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

在我的代码中,例如:

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")
  }
}

谢谢。

请记住,您仍然可以在很大程度上使用Scala中的Java反射,在某些情况下可能会简单一些。这本身就很复杂,您必须解析(即遍历和模式匹配)整个语法树,并检查所有可能的情况(
常量
类符号
,方法)(例如
apply
method of
List
)和许多其他情况)。有关更多信息,您可以参考
scala.ref.api
特别是
常量的文档。