Javaでよく使っているし、使えるが、作りはしないもの。
それが、私にとってはアノテーションです。
今まで、それで問題ないのではとおもっていましたが、JavaのRESTful、つまり、JAX-RSをみるにあたり、
改めて、見てみる事にしました。

さて、RESTfulで、Javaのソース内で、

@GET
@Path("/foo")
public void foo(@PathParam("arg1") String arg1){
}

みたいな記述ができるのですが、これらの情報をどうやってとっているのかとか、ある程度まとめました。

まず、アノテーションの作成方法ですが、

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassAnnotation {
}

のような感じで、アノテーションを作成します。
interfaceのような宣言ですが、頭に@がついています。

これで、

@ClassAnnotation

が使えるようになるわけです。
ただし、ソースのどこでもつかえるという訳ではなく、
この指定はクラス宣言のアノテーションとして記述できますが、メソッドのアノテーションにはできません。
そのあたりを決めているのが、@Targetです。

その、@Targetですが、ElementTypeの定数をセットできます。
複数の場所に記述できるようにしたければ、

@Target({ElementType.TYPE, ElementType.PARAMETER})

のようにして、複数指定します。

また、

@Retention(RetentionPolicy.RUNTIME)

を記述しないと、実行時に取得できません。
詳しくは、こちらをご覧ください。

では、実際に使って見ます。

アノテーションの利用

@ClassAnnotation
@ClassValueAnnotation("this is annotaion value")
public class ClassAnnotItem {

}

ClassAnnotationの宣言

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassAnnotation {
}

ClassValueAnnotationの宣言

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassValueAnnotation {
	String value();
}

のような記述をしたものから、実際にプログラムで何というアノテーションが指定されているのかを調べます。

public static void classAnnotationSample1(){
		Annotation annotList[] = ClassAnnotItem.class.getAnnotations();
		
		System.out.println("annotaion size is [" + annotList.length + "]");
		for(int i=0; i<annotlist .length; i++){
			Annotation annon = annotList&#91;i&#93;;
			System.out.println("annotation class is &#91;" + annon.annotationType().getName() + "&#93;");
			
			if(annon instanceof ClassValueAnnotation){
				
				ClassValueAnnotation annonVal = (ClassValueAnnotation)annon;
				System.out.println(" |--> value is '" + annonVal.value() + "'");
			}
		}
}

を実行した結果が

annotaion size is [2]
annotation class is [annot.ClassAnnotation]
annotation class is [annot.ClassValueAnnotation]
 |--> value is 'this is annotaion value'

こんな感じに取得することができます。
たとえば、メソッド指定のアノテーションの場合には、

public static void methodAnnotationSample3(){
		
		//	メソッドのアノテーションが調べたければ、メソッドを取得してから
		Method methodList[] = SubclassMethodAnnotItem.class.getDeclaredMethods();
		System.out.println("method size is [" + methodList.length + "]");
		for(int i=0; i<methodlist .length; i++){
			Method method = methodList&#91;i&#93;;
			System.out.println("method name is #" + method.getName() + "()");

			for(Annotation anno: method.getAnnotations()){
				System.out.println(" |--> annotaion class is [" + anno.annotationType().getName() + "]");
			}
		}
}

のように、ReflectionをもちいてMethodを取得してから、そのメソッドに対してClassと同じように取得すればいいわけです。

では、

@ClassKVAnnotaion(boolVal=true,intVal=10,strVal="this is string value")
public class ClassKVAnnotItem {

}

のように、キーと値を指定できる記述ができるアノテーションを作るにはどうしたらよいかと言えば、

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ClassKVAnnotaion {
	String 	strVal();
	int 	intVal();
	boolean boolVal();
}

のようにすればよいわけです。

では、

public class FieldAnnotItem {	
	@FieldAnnotation("sample1")
	private 	String privateField;
	
	@FieldAnnotation("sample2")
	protected 	String protectedFideld;
	
	//	デフォルトを指定しているので、値を省略できる
	@FieldAnnotation()
	public		String publicField;
}

のように、値を入れることもできたり、省略することもできるアノテーションはといえば、

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldAnnotation {
	String value() default "this is default value";
}

のようになりdefaultの指示をすることになります。(なんか、SQLみたいです)

ちなみに、valueだけは(value=”foo”)とも(“foo”)とも記述できます。
それ以外はだめなようです。

public static void fieldAnnotaitonSample1(){
		
		// 
		Field fieldList[] = FieldAnnotItem.class.getDeclaredFields();
		for(Field field: fieldList){
			System.out.println("field is [" + field.getName().toString() + "]");
			Annotation annonList[] = field.getDeclaredAnnotations();
			for(Annotation annot: annonList){
				System.out.println(" |--> annontaion is [" + annot.annotationType().getName() + "]");
				if(annot instanceof FieldAnnotation){
					System.out.println("   |--> value is '" + ((FieldAnnotation) annot).value() + "'");
				}
			}
		}
}

を実行すれば、

field is [privateField]
 |--> annontaion is [annot.FieldAnnotation]
   |--> value is 'sample1'
field is [protectedFideld]
 |--> annontaion is [annot.FieldAnnotation]
   |--> value is 'sample2'
field is [publicField]
 |--> annontaion is [annot.FieldAnnotation]
   |--> value is 'this is default value'

となり、キチンとデフォルト値がとれています。

最後は、引数の中のアノテーションですが、

public class ParamsAnnotItem {

	public void check1(@ParamAnnotation("id") String id, @ParamAnnotation("value") String value){
		
	}
	
	public void check2(@ParamAnnotation("arg0-0") @MultiAnnotation String id){
		
	}
}

のように記述したあるものとします。
ここで、@ParamAnnotationと@MultiAnntationの宣言は省略します。

public static void paramsAnnotationSample1(){
		
		//		メソッドのアノテーションが調べたければ、メソッドを取得してから
		Method methodList[] = ParamsAnnotItem.class.getDeclaredMethods();
		System.out.println("method size is [" + methodList.length + "]");
		for(Method method: methodList){
			System.out.println("method name is #" + method.getName() + "()");
			
			Annotation params[][] = method.getParameterAnnotations();
			System.out.println(" |--> params length is " + params.length);
			for(int i=0; i < params.length; i++){
				for(Annotation arg: params[i]){
					System.out.print( "     |--> arg[" + i + "]:" + arg.annotationType().getName());
					if(arg instanceof ParamAnnotation){
						System.out.println("('" + ((ParamAnnotation)arg).value().toString() + "')");
					}
					else{
						System.out.println();
					}
				}
			}
		}
}

を実行すれば

method size is [2]
method name is #check1()
 |--> params length is 2
     |--> arg[0]:annot.ParamAnnotation('id')
     |--> arg[1]:annot.ParamAnnotation('value')
method name is #check2()
 |--> params length is 1
     |--> arg[0]:annot.ParamAnnotation('arg0-0')
     |--> arg[0]:annot.MultiAnnotation

と表示されます。

まだ、細かい部分で足りない部分もありますが、
おおよその理解はできているはずです。

XMLやpropertiesファイルでの外部指定がよいのか、
アノテーションによるプログラム指定がいいのかは、
好みとケースで異なるでしょうが、
結構便利なだと思います。

お仕事のご依頼・相談を承ります
この記事に関連するお仕事のご依頼やご相談をお待ちしております。 詳しくは、こちら

Leave a Reply

お仕事のご依頼・相談
この記事に関連するお仕事のご依頼やご相談をお待ちしております。 詳しくは、こちら
ソフトウェア&ライブラリ




ライブラリ
airxmail(en)
AIR版メール送受信ライブラリ
airxzip
AIR版ZIP圧縮・解凍ライブラリ
執筆書籍
本、雑誌等

WEB記事:CodeZine
執筆記事はこちら
カレンダー
2011年11月
« 10月   12月 »
 123456
78910111213
14151617181920
21222324252627
282930  

カスタム検索
RSS
Add to Google < !–adsense–>
アーカイブ
カテゴリ
にほんブログ村 IT技術ブログへ