如何在 Scala 2.11 中获取方法的注释 [英] How to get the annotations of a method in Scala 2.11

查看:50
本文介绍了如何在 Scala 2.11 中获取方法的注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们假设一个控制器对象是这样的:

Let's assume a controller object like this:

object Users extends Controller {

  ...

  @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 authenticate = SecuredAction[Users.type]("authenticate").async(parse.json) { implicit request =>
    ...
  }

  ...
}

如何在运行时获取authenticate 方法的注解值?我试过这个:

How do I get the annotation values of the authenticate method at runtime? I've tried this:

def methodAnnotations[T: TypeTag]: Map[String, Map[String, Map[String, JavaArgument]]] = {
  typeTag[T].tpe.declarations.collect { case m: MethodSymbol => m }.map { m =>
    val methodName = m.name.toString
    val annotations =  m.annotations.map { a =>
      val annotationName = a.tpe.typeSymbol.name.toString
      val annotationArgs = a.javaArgs.map {
        case (name, value) => name.toString -> value
      }
      annotationName -> annotationArgs
    }.toMap
    methodName -> annotations
  }.toMap
}   

methodAnnotations 返回指定方法的指定注解并像这样调用:

methodAnnotations returns the specified annotation for the specified method and is invoke like this:

val mAnnotations = methodAnnotations[T]
val nickname = mAnnotations("myMethodName")("MyAnnotationName")("myAnnotationMemberName").asInstanceOf[LiteralArgument].value.value.asInstanceOf[String]

问题是,当我编译上面的代码时,我总是收到以下警告:

The problem is that when I compile the code above I always get the following warnings:

type JavaArgument in trait Annotations is deprecated: Use `Annotation.tree` to inspect annotation arguments
method tpe in trait AnnotationApi is deprecated: Use `tree.tpe` instead

使用 scala 2.11 获取方法注释的正确方法是什么?

What's the correct way to get method annotations with scala 2.11?

推荐答案

大概是 Nate 建议的方案是最多的干净而高效……但在我的情况下,它需要太多的重构,所以我决定仍然使用 Scala 反射.这是我的解决方案:

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

希望能帮到你.

这篇关于如何在 Scala 2.11 中获取方法的注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆