Reflectionsライブラリーのガイド

1.  前書き

https://github.com/ronmamo/reflections[_Reflections_]ライブラリはクラスパススキャナーとして機能します。 スキャンされたメタデータにインデックスを付け、実行時にクエリを実行できるようにします。 また、この情報を保存できるため、クラスパスを再スキャンすることなく、プロジェクト中の任意の時点で情報を収集して使用できます。
このチュートリアルでは、_Reflections_ライブラリを設定し、それをJavaプロジェクトで使用する方法を示します。

2. メーベン依存

_Reflections_を使用するには、プロジェクトにその依存関係を含める必要があります。
<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.11</version>
</dependency>
ライブラリhttps://search.maven.org/search?q=g:org.reflections%20AND%20a:reflections[Maven Central]の最新バージョンを見つけることができます。

3. _Reflections_の構成

次に、ライブラリを構成する必要があります。 *構成の主要な要素はURLとスキャナーです。*
URLはライブラリにクラスパスのどの部分をスキャンするかを指示しますが、スキャナーは指定されたURLをスキャンするオブジェクトです。
スキャナーが構成されていない場合、ライブラリは_TypeAnnotationsScanner_および_SubTypesScanner_をデフォルトとして使用します。

3.1. URLを追加する

_Reflections_を構成するには、構成の要素をvarargsコンストラクターのパラメーターとして提供するか、_ConfigurationBuilder_オブジェクトを使用します。
たとえば、パッケージ名、クラス、またはクラスローダーを表す_String_を使用して_Reflections_をインスタンス化することにより、URLを追加できます。
Reflections reflections = new Reflections("com.baeldung.reflections");
Reflections reflections = new Reflections(MyClass.class);
Reflections reflections = new Reflections(MyClass.class.getClassLoader());
さらに、_Reflections_には可変引数コンストラクターがあるため、上記の構成のすべてのタイプを組み合わせてインスタンス化できます。
Reflections reflections = new Reflections("com.baeldung.reflections", MyClass.class);
ここでは、スキャンするパッケージとクラスを指定してURLを追加しています。
_ConfigurationBuilder_を使用して同じ結果を得ることができます。
Reflections reflections = new Reflections(new ConfigurationBuilder()
  .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections"))));
_ClassPackHelper_は、_forPackage()_メソッドとともに、configuration_forClass()_や_forClassLoader()_などの他のメソッドを提供して、構成にURLを追加します。

3.2. スキャナーを追加する

  • Reflectionsライブラリには多くの組み込みスキャナーが付属しています:*

  • _FieldAnnotationsScanner –フィールドの注釈を探します

  • _MethodParameterScanner –メソッド/コンストラクタをスキャンしてからインデックスをスキャン
    パラメーター、および型とパラメーターの注釈を返します

  • _MethodParameterNamesScanner –メソッド/コンストラクタを検査し、その後
    インデックスパラメータ名

  • _TypeElementsScanner –フィールドとメソッドを調べてから、
    キーとしての完全修飾名、および値としての要素

  • _MemberUsageScanner –メソッド/コンストラクタ/フィールドの使用法をスキャンします

  • _TypeAnnotationsScanner –_クラスのランタイム注釈を探します

  • _SubTypesScanner – _super_クラスおよびインターフェイスの検索
    クラス、サブタイプの逆ルックアップを許可

  • _MethodAnnotationsScanner –_メソッドの注釈をスキャンします

  • _ResourcesScanner –コレクション内のすべての非クラスリソースを収集します

    _Reflections_â€〜コンストラクターのパラメーターとしてスキャナーを構成に追加できます。
    たとえば、上記のリストから最初の2つのスキャナーを追加しましょう。
Reflections reflections = new Reflections("com.baeldung.reflections"),
  new FieldAnnotationsScanner(),
  new MethodParameterScanner());
繰り返しますが、2つのスキャナーは_ConfigurationBuilder_ヘルパークラスを使用して構成できます。
Reflections reflections = new Reflections(new ConfigurationBuilder()
  .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections"))
  .setScanners(new FieldAnnotationsScanner(), new MethodParameterScanner()));

3.3. _ExecutorService_の追加

URLとスキャナーに加えて、* _ Reflections_はlink:/java-executor-service-tutorial[_ExecutorService_]*を使用してクラスパスを非同期にスキャンする可能性を提供します。
_Reflections_ ’コンストラクターのパラメーターとして、または_ConfigurationBuilder_を介して追加できます。
Reflections reflections = new Reflections(new ConfigurationBuilder()
  .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections"))
  .setScanners(new SubTypesScanner(), new TypeAnnotationsScanner())
  .setExecutorService(Executors.newFixedThreadPool(4)));
別のオプションは、単に_useParallelExecutor()_メソッドを呼び出すことです。 このメソッドは、デフォルトの_FixedThreadPool_ _ExecutorService_を、使用可能なコアプロセッサの数に等しいサイズで構成します。

3.4. フィルターを追加する

もう1つの重要な構成要素はフィルターです。 *フィルターは、スキャナーにクラスパスをスキャンするときに含めるものと除外するものを指示します*。
例として、テストパッケージのスキャンを除外するようにフィルターを構成できます。
Reflections reflections = new Reflections(new ConfigurationBuilder()
  .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections"))
  .setScanners(new SubTypesScanner(), new TypeAnnotationsScanner())
  .filterInputsBy(new FilterBuilder().excludePackage("com.baeldung.reflections.test")));
ここまでで、_Reflections_ ’構成のさまざまな要素の概要を簡単に説明しました。 次に、ライブラリの使用方法について説明します。

4. リフレクションを使用したクエリ

_Reflections_コンストラクターの1つを呼び出した後、構成されたスキャナーは提供されたすべてのURLをスキャンします。 次に、*スキャナーはそれぞれのスキャナーに対して、結果を_Multimap_ストアに格納します*。 そのため、_Reflections_を使用するには、提供されたクエリメソッドを呼び出してこれらのストアをクエリする必要があります。
これらのクエリメソッドの例を見てみましょう。

4.1. サブタイプ

_Reflections_が提供するすべてのスキャナーを取得することから始めましょう。
public Set<Class<? extends Scanner>> getReflectionsSubTypes() {
    Reflections reflections = new Reflections(
      "org.reflections", new SubTypesScanner());
    return reflections.getSubTypesOf(Scanner.class);
}

4.2. 注釈付きのタイプ

次に、特定の注釈を実装するすべてのクラスとインターフェースを取得できます。
したがって、__ java.util.function __packageのすべての機能インターフェイスを取得しましょう。
public Set<Class<?>> getJDKFunctinalInterfaces() {
    Reflections reflections = new Reflections("java.util.function",
      new TypeAnnotationsScanner());
    return reflections.getTypesAnnotatedWith(FunctionalInterface.class);
}

4.3. 注釈付きメソッド

ここで、_MethodAnnotationsScanner_を使用して、特定の注釈が付けられたすべてのメソッドを取得します。
public Set<Method> getDateDeprecatedMethods() {
    Reflections reflections = new Reflections(
      "java.util.Date",
      new MethodAnnotationsScanner());
    return reflections.getMethodsAnnotatedWith(Deprecated.class);
}

4.4. 注釈付きコンストラクタ

また、非推奨のコンストラクターをすべて取得できます。
public Set<Constructor> getDateDeprecatedConstructors() {
    Reflections reflections = new Reflections(
      "java.util.Date",
      new MethodAnnotationsScanner());
    return reflections.getConstructorsAnnotatedWith(Deprecated.class);
}

4.5. メソッドのパラメーター

さらに、_MethodParameterScanner_を使用して、特定のパラメータータイプを持つすべてのメソッドを検索できます。
public Set<Method> getMethodsWithDateParam() {
    Reflections reflections = new Reflections(
      java.text.SimpleDateFormat.class,
      new MethodParameterScanner());
    return reflections.getMethodsMatchParams(Date.class);
}

4.6. メソッドの戻り値の型

さらに、同じスキャナーを使用して、指定された戻り値の型を持つすべてのメソッドを取得することもできます。
_void_を返す_SimpleDateFormat_のすべてのメソッドを検索することを想像してみましょう。
public Set<Method> getMethodsWithVoidReturn() {
    Reflections reflections = new Reflections(
      "java.text.SimpleDateFormat",
      new MethodParameterScanner());
    return reflections.getMethodsReturn(void.class);
}

4.7. リソース

最後に、_ResourcesScanner_を使用して、クラスパスで特定のファイル名を探しましょう。
public Set<String> getPomXmlPaths() {
    Reflections reflections = new Reflections(new ResourcesScanner());
    return reflections.getResources(Pattern.compile(".*pom\\.xml"));
}

4.8. 追加のクエリメソッド

上記は、_Reflections'_クエリメソッドの使用方法を示すほんの一例です。 ただし、ここでは取り上げていない他のクエリメソッドもあります。
  • getMethodsWithAnyParamAnnotated

  • getConstructorsMatchParams

  • getConstructorsWithAnyParamAnnotated

  • getFieldsAnnotatedWith

  • getMethodParamNames

  • getConstructorParamNames

  • getFieldUsage

  • getMethodUsage

  • getConstructorUsage

5. _Reflections_をビルドライフサイクルに統合する

https://search.maven.org/search?q=a:gmavenplus-plugin%20AND%20g:org.codehaus.gmavenplus[_gmavenplus-plugin_]を使用して、_Reflections_をMavenビルドに簡単に統合できます。
スキャンの結果をファイルに保存するように設定しましょう:
<plugin>
    <groupId>org.codehaus.gmavenplus</groupId>
    <artifactId>gmavenplus-plugin</artifactId>
    <version>1.5</version>
    <executions>
        <execution>
            <phase>generate-resources</phase>
            <goals>
                <goal>execute</goal>
            </goals>
            <configuration>
                <scripts>
                    <script><![CDATA[
                        new org.reflections.Reflections(
                          "com.baeldung.refelections")
                            .save("${outputDirectory}/META-INF/reflections/reflections.xml")]]>
                    </script>
                </scripts>
            </configuration>
        </execution>
    </executions>
</plugin>
後で、_collect()_メソッドを呼び出すことにより、*保存された結果を取得**でき、新しいスキャンを実行せずに、さらに使用できるようになります:*
Reflections reflections
  = isProduction() ? Reflections.collect() : new Reflections("com.baeldung.reflections");

6. 結論

この記事では、_Reflections_ライブラリを調べました。 さまざまな構成要素とその使用法について説明しました。 そして最後に、_Reflections_をMavenプロジェクトのビルドライフサイクルに統合する方法を見ました。
いつものように、完全なコードは、https://github.com/eugenp/tutorials/tree/master/libraries [GitHub]で入手できます。