如何在Scala/Java运行时找到已注解的方法

huangapple go评论71阅读模式
英文:

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

问题

我想要使用运行时反射与Scala注解如果必要的话也可以是Java注解但我更倾向于限制纯Java代码)。

我想要实现类似于

    /**
      打印所有带有特定注解的方法
    */
     def getAllAnnotated(): Unit {...}

例如如果我有
```scala
class Foo {
    @printme
    def foo(args: A): R
    
    def oof(args: A): R
}
class Bar {
    @printme
    def bar(): Unit
}

运行 getAllAnnotated() 的结果可能是:

Foo.foo
Bar.bar

请注意,我不想查找特定的类,而是查找任何可用的方法。


<details>
<summary>英文:</summary>

I want to use Runtime Reflection with Scala annotations (could also be a Java annoations if necessary, but I would prefer to limit pure Java code)

I want to implement something like:

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

For example, if I have:

class Foo {
@printme
def foo(args: A): R

def oof(args: A): R

}
class Bar {
@printme
def bar(): Unit
}

The result of running `getAllAnnotated()` would be something like:

Foo.foo
Bar.bar


Note that I don&#39;t want to look in a specific class, but instead any available method

</details>


# 答案1
**得分**: 2

尝试使用基于Java反射的类路径扫描器之一(例如[Reflections][1]) + [scala-reflect][2]。由于我们仅使用Java反射来查找类,并使用scala-reflect来查找带注释的方法,因此注释可以用Scala编写。

```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库的替代方案包括ClassGraphBurningwave。如果我们用Java反射替换scala-reflect,那么注释必须用Java编写,因为只有使用Java编写的注释在运行时才能通过Java反射可见。

英文:

Try one of classpath scanners based on Java reflection (e.g. Reflections) + scala-reflect. Since we use Java reflection only to look for classes and scala-reflect to look for annotated methods, annotations can be written in 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(&quot;&quot;))
    .setScanners(new SubTypesScanner(false))
)

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

Alternatives to Reflections library are for example ClassGraph and Burningwave. If we replace scala-reflect with Java reflection then annotation will have to be written in Java because only annotations written in Java are visible at runtime with Java reflection.

答案2

得分: 1

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

英文:

In Java you can scan for the classes in the package using reflection Using Reflections to get all classes of the package and then recursively go inside all the classes to find the annotations.

huangapple
  • 本文由 发表于 2020年9月26日 02:58:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/64069971.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定