1. 序章

Reflectionsライブラリはクラスパススキャナーとして機能します。 スキャンされたメタデータにインデックスを付け、実行時にクエリを実行できるようにします。 また、この情報を保存できるため、クラスパスを再度スキャンすることなく、プロジェクト中の任意の時点で情報を収集して使用できます。

このチュートリアルでは、 Reflections ライブラリを構成し、Javaプロジェクトで使用する方法を示します。

2. Mavenの依存関係

Reflections を使用するには、プロジェクトにその依存関係を含める必要があります。

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.11</version>
</dependency>

ライブラリの最新バージョンはMavenCentralにあります。

3. 反射の構成

次に、ライブラリを構成する必要があります。 構成の主な要素は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 にはvarargsコンストラクターがあるため、上記のすべての構成の型を組み合わせてインスタンス化できます。

Reflections reflections = new Reflections("com.baeldung.reflections", MyClass.class);

ここでは、スキャンするパッケージとクラスを指定してURLを追加しています。

ConfigurationBuilder を使用しても、同じ結果を得ることができます。

Reflections reflections = new Reflections(new ConfigurationBuilder()
  .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections"))));

forPackage()メソッドとともに、 Classp ath Helpe r は、などの他のメソッドを提供します。 ] 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());

この場合も、ConfigurationBuilderヘルパークラスを使用して2つのスキャナーを構成できます。

Reflections reflections = new Reflections(new ConfigurationBuilder()
  .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections"))
  .setScanners(new FieldAnnotationsScanner(), new MethodParameterScanner()));

3.3. ExecutorServiceの追加

URLとスキャナーに加えて、 Reflectionsは、ExecutorServiceを使用してクラスパスを非同期的にスキャンする可能性を提供します。

Reflections ‘コンストラクターのパラメーターとして、またはConfigurationBuilderを介して追加できます。

Reflections reflections = new Reflections(new ConfigurationBuilder()
  .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections"))
  .setScanners(new SubTypesScanner(), new TypeAnnotationsScanner())
  .setExecutorService(Executors.newFixedThreadPool(4)));

もう1つのオプションは、 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をスキャンします。 次に、スキャナーごとに、ライブラリは結果をマルチマップストアに配置します。 その結果、 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パッケージのすべての機能インターフェイスを取得しましょう。

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をビルドライフサイクルに統合する

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()メソッドを呼び出すことにより、保存された結果 を取得し、新しいスキャンを実行しなくても、後で使用できるようにすることができます。[X177X ]

Reflections reflections
  = isProduction() ? Reflections.collect() : new Reflections("com.baeldung.reflections");

6. 結論

この記事では、Reflectionsライブラリについて説明しました。 さまざまな構成要素とその使用法について説明しました。 そして最後に、ReflectionsをMavenプロジェクトのビルドライフサイクルに統合する方法を見ました。

いつものように、完全なコードはGitHubで入手できます。