前回に引き続き、アノテーションについて書こうかと思います。
アノテーションについては、前回の記事を参照してください。
今回は、ありがちな例となってしまうのですが、
入力値のチェック処理での活用方法をご紹介します。
まず、チェック内容をあらわすアノテーションを宣言し、
そのアノテーションを、Bean の getter メソッドに対して宣言します。
(1)チェック内容をあらわすアノテーションを宣言します。
----------------------------------------------------------------------
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiredCheck {
String value(); //←(a)
}
----------------------------------------------------------------------
上記のコードでは、(a)のように、アノテーションにメソッドを宣言しています。
このように、アノテーションにはメソッドを宣言してメンバを保有することができます。
ただし、アノテーションの実体はインタフェースなので、
メソッドの具体的な挙動を記述することはできません。
メソッドは複数宣言することもできます。
上記のように単一のメソッドだけを宣言する場合は、
value()というメソッドを宣言するのが御作法のようです。
使用方法については、(2)の部分で行います。
(2)アノテーションを、TestBeanクラスのgetterメソッドに対して宣言します。
----------------------------------------------------------------------
import org.light.annotation.RequiredCheck;
public class TestBean {
private String param = "";
public void setParam(String param) {
this.param = param;
}
@RequiredCheck("項目1")
public String getParam() {
return this.param;
}
}
----------------------------------------------------------------------
上記のように、アノテーションに宣言したメソッドは、
アノテーションの型名に続いて ( ) でメンバの値を初期化する必要があります。
上記では、必須入力チェックを表す RequiredCheck アノテーションを
getParam()メソッドに対して宣言し、項目名を "項目1" で初期化しています。
※ここで宣言した項目名は、エラーメッセージを表示する際に使用します。
RequiredCheck アノテーションはメンバを保有しているため、
アノテーションを指定したときに ( ) 内にアノテーションの
メンバを初期化させなければなりません。
ちなみに、RequiredCheck アノテーションは、
宣言されているメソッドが1つで、且つ、value()というメソッドを宣言しているため、
@アノテーション型(値)という宣言で済みます。
これは、value()というメソッドが言語で予約されているためです。
通常は、@アノテーション型(メソッド名=値)と宣言する必要があります。
上記の場合だと、「@RequiredCheck(value="項目1")」となります。
複数メソッドが宣言されていた場合は、
@アノテーション型(メソッド名=値,メソッド名=値,...)と宣言します。
(3)TestBean クラスの入力チェックを行います。
----------------------------------------------------------------------
public static void main(String[] args) throws Exception {
TestBean bean = new TestBean();
bean.setParam("");
Class clazz = bean.getClass();
BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
// TestBean のプロパティメソッドの情報を全て取得する
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
for (int i1 = 0; i1 < pds.length; i1++) {
// getter メソッドに宣言されているアノテーション情報を取得する
Method method = pds[i1].getReadMethod();
Annotation[] annotations = method.getDeclaredAnnotations();
for (int i2 = 0; i2 < annotations.length; i2++) {
internalValidate(bean, annotations[i2], method);
}
}
}
private static void internalValidate(Object bean
, Annotation annotation
, Method method) throws Exception {
// アノテーションが RequiredCheck の場合、必須入力チェックを行う。
if ( annotation instanceof RequiredCheck) {
String sValue = (String)method.invoke(bean, new Object[0]);
if ( sValue == null || "".equals(sValue) ) {
// エラーの場合、RequiredCheck アノテーションの
// value()メソッドから項目名を取得してメッセージを生成する
RequiredCheck req = (RequiredCheck)annotation;
System.out.println(req.value() + "は、必須入力です。");
}
}
}
----------------------------------------------------------------------
(4)実行結果
----------------------------------------------------------------------
項目1は、必須入力です。
----------------------------------------------------------------------
以上のようにアノテーションを利用すれば、
どの項目に対して、どのような入力チェック処理を実行するかを、
自由に宣言することができます。
こうすることによって、入力チェックロジックを個別に実装せずに、
自動的にチェック処理を実行することが可能になります。