How to get the annotations of a method in Scala 2.11

左心房为你撑大大i 提交于 2019-12-04 21:05:44

If you can handle using Jackson, then I'd re-use its annotation processing functionality instead of using scala reflection.

object Test {
  import com.fasterxml.jackson.databind.introspect.{AnnotatedClass, JacksonAnnotationIntrospector}

  @ApiOperation(
    httpMethod = "POST",
    nickname = "authenticate",
    value = "Authenticates an user",
    notes = "Returns the JSON Web Token to be used in any subsequent request",
    response = classOf[models.auth.api.Jwt])
  def hasAnnotation() {}

  def main(args: Array[String]): Unit = {
    import scala.collection.JavaConversions._

    val introspector = new JacksonAnnotationIntrospector
    val ac = AnnotatedClass.construct(Test.getClass, introspector, null)
    for (method <- ac.memberMethods()) {
      val annotation = method.getAnnotation(classOf[ApiOperation])
      if (annotation != null) {
        println(s"${method.getFullName} -> ${annotation.nickname()}")
      }
    }
  }
}
j3d

Probably the solution suggested by Nate is the most clean and efficient... but in my case it would require too much refactoring, so I've just decided to still use Scala reflection. Here is my solution:

package utils.common

import scala.reflect.runtime.universe._

/**
  * Provides functionality for obtaining reflective information about
  * classes and objects.
  */
object ReflectHelper {

  /**
    * Returns a `Map` from annotation names to annotation data for
    * the specified type.
    *
    * @tparam T The type to get class annotations for.
    * @return The class annotations for `T`.
    */
  def classAnnotations[T: TypeTag]: Map[String, Map[String, Any]] = {
    typeOf[T].typeSymbol.asClass.annotations.map { a =>
      a.tree.tpe.typeSymbol.name.toString -> a.tree.children.withFilter {
        _.productPrefix eq "AssignOrNamedArg"
      }.map { tree =>
        tree.productElement(0).toString -> tree.productElement(1)
      }.toMap
    }.toMap
  }

  /**
    * Returns a `Map` from method names to a `Map` from annotation names to
    * annotation data for the specified type.
    *
    * @tparam T The type to get method annotations for.
    * @return The method annotations for `T`.
    */
  def methodAnnotations[T: TypeTag]: Map[String, Map[String, Map[String, Any]]] = {
    typeOf[T].decls.collect { case m: MethodSymbol => m }.withFilter {
      _.annotations.length > 0
    }.map { m =>
      m.name.toString -> m.annotations.map { a =>
        a.tree.tpe.typeSymbol.name.toString -> a.tree.children.withFilter {
         _.productPrefix eq "AssignOrNamedArg"
        }.map { tree =>
          tree.productElement(0).toString -> tree.productElement(1)
        }.toMap
      }.toMap
    }.toMap
  }
}

I hope it helps.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!