如何在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 ofList
)和许多其他情况)。有关更多信息,您可以参考scala.ref.api
特别是常量的文档。