リフレクションはクラスパスをスキャンすることでメタデータにインデックスを付け、実行時にこれらのメタデータをクエリできるようにします。また、プロジェクト内の複数のモジュールのメタデータ情報を保存および収集することもできます。
リフレクションを使用して、指定したパッケージの下にあるカスタマイズされたコントローラーと RequestMapping アノテーションをすばやくスキャンします。最初に @Controller アノテーションが付けられたクラスをスキャンし、次にこれらのクラスの下で @RequestMapping アノテーションが付けられたメソッドを取得してから、Java リフレクション メソッドを呼び出します。アノテーションが付けられたメソッドを呼び出します。 RequestMapping を使用してアノテーション付きの情報を出力します。
Maven プロジェクトのインポート
<dependency> <groupId>org.reflections</groupId> <artifactId>reflections</artifactId> <version>0.9.10</version> </dependency>
アノテーション パッケージの下で 2 つのアノテーションがカスタマイズされています。
Controller.java:
package annotationTest.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE)// 注解会在class字节码文件中存在,在运行时可以通过反射获取到 @Retention(RetentionPolicy.RUNTIME)//定义注解的作用目标**作用范围字段、枚举的常量/方法 @Documented//说明该注解将被包含在javadoc中 public @interface Controller { String value() default ""; }
RequestMapping.java
package annotationTest.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface RequestMapping { String value() default ""; /** * 是否为序列号 * * @return */ boolean id() default false; /** * 字段名称 * * @return */ String name() default ""; /** * 字段描述 * * @return */ String description() default ""; }
RequestMapping アノテーション メソッドを格納するオブジェクトはモデル パッケージの下で定義されます
ExecutorBean.java
package annotationTest.model; import java.lang.reflect.Method; public class ExecutorBean { private Object object; private Method method; public Object getObject() { return object; } public void setObject(Object object) { this.object = object; } public Method getMethod() { return method; } public void setMethod(Method method) { this.method = method; } }
いくつかのクラスはサービス パッケージの下で定義されます。カスタム コントローラー アノテーションを使用するクラスが 2 つあります
SunService.java
package annotationTest.service; import annotationTest.annotation.Controller; import annotationTest.annotation.RequestMapping; @Controller public class SunService { @RequestMapping(id = true, name = "test1", description = "sun测试1", value = "/test1") public void test1() { System.out.println("SunService->test1()"); } @RequestMapping(id = true, name = "test2", description = "sun测试2", value = "/test2") public void test2() { System.out.println("SunService->test2()"); } }
MoonService.java
package annotationTest.service; import annotationTest.annotation.Controller; import annotationTest.annotation.RequestMapping; @Controller public class MoonService { @RequestMapping(id = true, name = "moon测试3", description = "/test3", value = "/test3") public void test3() { System.out.println("MoonService->test3()"); } @RequestMapping(id = true, name = "moon测试4", description = "/test4", value = "/test4") public void test4() { System.out.println("MoonService->test4()"); } }
Stars.java
package annotationTest.service; import annotationTest.annotation.RequestMapping; public class Stars { @RequestMapping(id = true, name = "test1", description = "stars测试1", value = "/test1") public void test1() { System.out.println("Stars->test1()"); } }
ツール クラスは、パッケージをスキャンしてカスタマイズを取得するために util パッケージの下に定義されています アノテーション付きクラスおよびメソッド
AnnoManageUtil.java
package annotationTest.util; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.Set; import annotationTest.annotation.Controller; import annotationTest.annotation.RequestMapping; import annotationTest.model.ExecutorBean; import org.reflections.Reflections; public final class AnnoManageUtil { /** * 获取指定文件下面的RequestMapping方法保存在mapp中 * * @param packageName * @return */ public static Map<String, ExecutorBean> getRequestMappingMethod(String packageName) { Reflections reflections = new Reflections(packageName); Set<Class<?>> classesList = reflections.getTypesAnnotatedWith(Controller.class); // 存放url和ExecutorBean的对应关系 Map<String, ExecutorBean> mapp = new HashMap<String, ExecutorBean>(); for (Class classes : classesList) { //得到该类下面的所有方法 Method[] methods = classes.getDeclaredMethods(); for (Method method : methods) { //得到该类下面的RequestMapping注解 RequestMapping requestMapping = method.getAnnotation(RequestMapping.class); if (null != requestMapping) { ExecutorBean executorBean = new ExecutorBean(); try { executorBean.setObject(classes.newInstance()); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } executorBean.setMethod(method); mapp.put(requestMapping.value(), executorBean); } } } return mapp; } }
以下はテストクラスです
package annotationTest.test; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.List; import java.util.Map; import annotationTest.annotation.Controller; import annotationTest.annotation.RequestMapping; import annotationTest.model.ExecutorBean; import annotationTest.util.AnnoManageUtil; public class Test { public static void main(String[] args) { List<Class<?>> classesList = null; classesList = AnnoManageUtil.getPackageController("annotationTest.service", Controller.class); Map<String, ExecutorBean> mmap = new HashMap<String, ExecutorBean>(); AnnoManageUtil.getRequestMappingMethod(classesList, mmap); ExecutorBean bean = mmap.get("/test1"); try { bean.getMethod().invoke(bean.getObject()); RequestMapping annotation = bean.getMethod().getAnnotation(RequestMapping.class); System.out.println("注解名称:" + annotation.name() + "\t注解描述:" + annotation.description()); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }
それを実行して取得します:
その他
リフレクションを使用して次のメタデータ情報をクエリします:
Reflections は、Google の Guava ライブラリと Javassist ライブラリに依存しています。
特定の型のすべてのサブタイプを取得します
特定の注釈でマークされたすべての型/メンバー変数を取得し、注釈パラメータのマッチングをサポートします。
正規表現を使用して、一致するすべてのリソースファイルを取得します
メソッドを使用して、すべての特定のシグネチャ (パラメータ、パラメータの注釈、戻り値を含む) を取得します
注釈を使用してクラス/メソッド/メンバー変数などを装飾しますその後、これらのアノテーションは単独では有効になりません (もちろん、アノテーションの定義時に @Retention (RetentionPolicy.RUNTIME) 変更が使用された場合に限ります)。 JVM はクラス ファイルをロードします。クラス ファイルに保存された注釈は実行時に表示されるため、それを解析できます)。 . このインターフェイスはすべての親インターフェイス用です。
java5 は、プログラム内で注釈を受け入れることができるプログラム要素を表す AnnotatedElement インターフェースを java.lang.reflect パッケージに追加しました。
AnnotatedElement インターフェースの実装クラスは、Class (クラス要素)、Field です。 (クラスのメンバー変数要素)、メソッド (クラスのメソッド要素)、パッケージ (パッケージ要素)、それぞれの実装クラスは、アノテーションを受け入れることができるプログラム要素の型を表します。
この方法で必要なのは、Class、Method、Filed、および AnnotatedElement インターフェースを実装するその他のクラスのインスタンスを取得し、インスタンス オブジェクトを通じてクラス内のメソッドを呼び出すことだけです (AnnotatedElement インターフェースの抽象メソッドのオーバーライド)。 ) を取得する これで、必要なアノテーション情報が得られました。
Class クラスのインスタンスを取得するには 3 つの方法があります:
クラスの静的な forName() メソッドを使用します。 Class クラスを作成し、クラス名を使用して Class インスタンスを取得します
.class を使用して、次のような Class インスタンスを取得します。 class name.class
Annotation[] getAnnotations()
< T extends Annotation> T getDeclaredAnnotation(Class < 指定されたタイプの注釈を使用してプログラム要素を直接変更します (継承された注釈は無視されます)。このタイプの注釈が存在しない場合は、null を返します。
Annotation[] getDeclaredAnnotations()
機能: この要素に直接存在するすべての注釈を返します。このメソッドは、継承された注釈を無視します。 (この要素に直接アノテーションが存在しない場合は、長さ 0 の配列が返されます。)
boolean isAnnotationPresent(Class extends Annotation> annotationClass)
関数: 指定されたタイプのアノテーションが存在するかどうかを判断します。プログラム要素。存在する場合は true を返し、存在しない場合は false を返します。
<T extends Annotation> T[] getAnnotationsByTpye(Class
機能: Java8 では反復アノテーション関数が追加されているため、プログラム要素を変更し、型を指定する複数のアノテーションを取得するには、このメソッドを使用する必要があります。
機能: Java8 では繰り返しアノテーション関数が追加されるため、プログラム要素を直接変更して指定する複数のアノテーションを取得するには、このメソッドを使用する必要があります。タイプ。 。
クラスは、getMethod()、getField()、および getConstructor() メソッド (およびその他のメソッド) を提供し、これらのメソッドはそれぞれ、メソッド、フィールド変数、およびコンストラクター型のオブジェクトを返します。 。
以上が指定したパッケージ内のすべてのカスタム アノテーションを取得しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。