JavaのリフレクションAPIでアノテーション取得
JavaのリフレクションAPIでアノテーションの取得を試してみたメモです。
前回の続きで、JavaのリフレクションAPIを利用して、アノテーションの取得を試してみました。
java.lang.reflect.AnnotatedElement
JavaのリフレクションAPIを利用することで、メタデータにアクセスできます。
java.lang.reflect.AnnotatedElementインターフェースを利用してアノテーションの取得を試したいと思います。
テスト用クラス
Mavenプロジェクトを作成し、pom.xmlはjunitとhamcrestだけdependencyに追加しました。
pom.xml
<dependencies> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest-all</artifactId> <version>1.3</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit-dep</artifactId> <version>4.10</version> <scope>test</scope> </dependency> </dependencies>
テスト対象のクラスは下記のようなクラスを作りました。
package reflect; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.RUNTIME; public class ReflectAnnotationExample { @FieldAnnotation public String name; @ConstructorAnnotaion public ReflectAnnotationExample(String name) { this.name = name; } @MethodAnnotation public String getName() { return name; } @Deprecated @ClassAnnotation public class DeprecatedClass { } @Target(FIELD) @Retention(RUNTIME) public @interface FieldAnnotation { } @Target(CONSTRUCTOR) @Retention(RUNTIME) public @interface ConstructorAnnotaion { } @Target(METHOD) @Retention(RUNTIME) public @interface MethodAnnotation { } @Target(TYPE) @Retention(RUNTIME) @Inherited public @interface ClassAnnotation { } }
フィールド、コンストラクタ、メソッド、クラスのりテンションポリシーで
それぞれアノテーションを作成しました。
それぞれのアノテーションをフィールド、コンストラクタ、メソッド、クラスに付与しました。
DeprecatedClassには追加で、@Deprecatedも付与しました。
getAnnotation()
getAnnotation()では、引数で指定したアノテーションが存在する場合、指定した型のアノテーションが取得できます。
指定したアノテーションが存在しない場合nullが返ります。
Annotation annotation = ReflectAnnotationExample.class.getAnnotation(ClassAnnotation.class);
getAnnotationメソッドは、AnnotatedElementインターフェースを実装しているクラスで使用できます。
Classクラス、Methodクラス、Fieldクラス、ConstructorクラスはAnnotationElementインターフェースを実装しています。
// Classクラス Class clazz = ReflectAnnotationExample.DeprecatedClass.class; Annotation anno = clazz.getAnnotation(ClassAnnotation.class); // Methodクラス Method method = ReflectAnnotationExample.class.getMethod("getName"); Annotation anno = method.getAnnotation(MethodAnnotation.class); // Fieldクラス Field field = ReflectAnnotationExample.class.getField("name"); Annotation anno = field.getAnnotation(FieldAnnotation.class); // Constructorクラス Constructor cons = ReflectAnnotationExample.class.getConstructor(String.class); Annotation anno = cons.getAnnotation(ConstructorAnnotaion.class);
テストコード。
public static class getAnnotationの確認 { @Test public void Classクラスからアノテーションが取得できること() throws Exception { Class clazz = ReflectAnnotationExample.DeprecatedClass.class; Annotation anno = clazz.getAnnotation(ClassAnnotation.class); assertThat(anno, is(instanceOf(ClassAnnotation.class))); } @Test public void Methodクラスからアノテーションが取得できること() throws Exception { Method method = ReflectAnnotationExample.class.getMethod("getName"); Annotation anno = method.getAnnotation(MethodAnnotation.class); assertThat(anno, is(instanceOf(MethodAnnotation.class))); } @Test public void Fieldクラスからアノテーションが取得できること() throws Exception { Field field = ReflectAnnotationExample.class.getField("name"); Annotation anno = field.getAnnotation(FieldAnnotation.class); assertThat(anno, is(instanceOf(FieldAnnotation.class))); } @Test public void Constructorクラスからアノテーションが取得できること() throws Exception { Constructor cons = ReflectAnnotationExample.class.getConstructor(String.class); Annotation anno = cons.getAnnotation(ConstructorAnnotaion.class); assertThat(anno, is(instanceOf(ConstructorAnnotaion.class))); } }
getAnnotations()
getAnnotations()では、要素に存在するすべてのアノテーションを取得できます。
要素にアノテーションが存在しない場合、長さ0の配列が返ります。
Annotation[] annotation = ReflectAnnotationExample.class.getAnnotations;
getAnnotationsメソッドは、AnnotatedElementインターフェースを実装しているクラスで使用できます。
Classクラス、Methodクラス、Fieldクラス、ConstructorクラスはAnnotationElementインターフェースを実装しています。
テストコード。
public static class getAnnotationsの確認 { @Test public void クラスのアノテーションが取得できること() throws Exception { Class clazz = ReflectAnnotationExample.DeprecatedClass.class; Annotation[] annos = clazz.getAnnotations(); Annotation[] expected = { clazz.getAnnotation(ClassAnnotation.class), clazz.getAnnotation(Deprecated.class) }; assertThat(annos, is(arrayContainingInAnyOrder(expected))); } @Test public void メソッドのアノテーションが取得できること() throws Exception { Method method = ReflectAnnotationExample.class.getMethod("getName"); Annotation[] annos = method.getAnnotations(); Annotation[] expected = { method.getAnnotation(MethodAnnotation.class) }; assertThat(annos, is(arrayContainingInAnyOrder(expected))); } }
テストコード
今回のテストコードの全体です。
ReflectAnnotationExampleTest.java
package reflect; import org.junit.Test; import org.junit.experimental.runners.Enclosed; import org.junit.runner.RunWith; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.arrayContainingInAnyOrder; import static org.junit.Assert.*; import static reflect.ReflectAnnotationExample.*; /** * Created by pppurple on 2016/07/26. */ @RunWith(Enclosed.class) public class ReflectAnnotationExampleTest { public static class getAnnotationの確認 { @Test public void Classクラスからアノテーションが取得できること() throws Exception { Class clazz = ReflectAnnotationExample.DeprecatedClass.class; Annotation anno = clazz.getAnnotation(ClassAnnotation.class); assertThat(anno, is(instanceOf(ClassAnnotation.class))); } @Test public void Methodクラスからアノテーションが取得できること() throws Exception { Method method = ReflectAnnotationExample.class.getMethod("getName"); Annotation anno = method.getAnnotation(MethodAnnotation.class); assertThat(anno, is(instanceOf(MethodAnnotation.class))); } @Test public void Fieldクラスからアノテーションが取得できること() throws Exception { Field field = ReflectAnnotationExample.class.getField("name"); Annotation anno = field.getAnnotation(FieldAnnotation.class); assertThat(anno, is(instanceOf(FieldAnnotation.class))); } @Test public void Constructorクラスからアノテーションが取得できること() throws Exception { Constructor cons = ReflectAnnotationExample.class.getConstructor(String.class); Annotation anno = cons.getAnnotation(ConstructorAnnotaion.class); assertThat(anno, is(instanceOf(ConstructorAnnotaion.class))); } } public static class getAnnotationsの確認 { @Test public void クラスのアノテーションが取得できること() throws Exception { Class clazz = ReflectAnnotationExample.DeprecatedClass.class; Annotation[] annos = clazz.getAnnotations(); Annotation[] expected = { clazz.getAnnotation(ClassAnnotation.class), clazz.getAnnotation(Deprecated.class) }; assertThat(annos, is(arrayContainingInAnyOrder(expected))); } @Test public void メソッドのアノテーションが取得できること() throws Exception { Method method = ReflectAnnotationExample.class.getMethod("getName"); Annotation[] annos = method.getAnnotations(); Annotation[] expected = { method.getAnnotation(MethodAnnotation.class) }; assertThat(annos, is(arrayContainingInAnyOrder(expected))); } } }
ソースはあげておきました。
github.com
終わり。