如何在运行时找到 Scala/Java 中的注释方法

How can I find Annotated methods in Scala/Java on Runtime

我想将运行时反射与 Scala 注释一起使用(如有必要,也可以是 Java 注释,但我更愿意限制纯 Java 代码)

我想实现类似的东西:

/**
  print all methods that implement a specific annotation
*/
 def getAllAnnotated(): Unit {...}

例如,如果我有:

class Foo {
    @printme
    def foo(args: A): R
    
    def oof(args: A): R
}
class Bar {
    @printme
    def bar(): Unit
}

运行 getAllAnnotated() 的结果类似于:

Foo.foo
Bar.bar

请注意,我不想查看特定的 class,而是查看任何可用的方法

在 Java 中,您可以使用反射扫描包中的 类 使用反射获取包的所有 类,然后递归进入所有 类 找到注释。

尝试一种基于 Java 反射的类路径扫描器(例如 Reflections) + scala-reflect。因为我们使用 Java 反射只是为了寻找 类 和 scala-reflect寻找带注解的方法,注解可以用Scala写。

import org.reflections.Reflections
import org.reflections.scanners.SubTypesScanner
import org.reflections.util.{ClasspathHelper, ConfigurationBuilder}
import scala.annotation.StaticAnnotation
import scala.jdk.CollectionConverters._
import scala.reflect.runtime.currentMirror
import scala.reflect.runtime.universe._

class printme extends StaticAnnotation

val reflections = new Reflections(
  (new ConfigurationBuilder)
    .setUrls(ClasspathHelper.forPackage(""))
    .setScanners(new SubTypesScanner(false))
)

def getAllAnnotated(): Unit =
  reflections.getAllTypes.asScala
    .flatMap(className =>
      currentMirror.classSymbol(Class.forName(className))
        .toType
        .decls
        .filter(symbol =>
          symbol.isMethod && symbol.annotations.exists(_.tree.tpe =:= typeOf[printme])
        )
        .map(method => s"$className.${method.name}")
    ).foreach(println)

Reflections 库的替代品例如 ClassGraph and Burningwave。如果我们将 scala-reflect 替换为 Java 反射,则必须在 Java 中编写注释,因为只有在 Java 中编写的注释在运行时使用 Java 反射可见。