Top / アノテーション
設定ファイル地獄という言葉がある。 設定中心のフレームワークが、設定だらけになって メンテナンスが地獄のように面倒になる現象だ。
ここで、アノテーションと呼ばれるものの登場である。
最初アノテーションと言う言葉を知ったときには、何につかうのか?と使い道が思いつかなかったのだが、どうやら、設定中心のフレームワークに応用すると、地獄から抜けられる。たとえば、Strutsに対するSAStrutsの登場である。
自分は、当初SAStrutsがあるんだから、それを使えばよいと思っていた。
しかしながら、SAStrutsは、独自の規約で作成しなくてはならないため、プロジェクトに応用できないということがわかってきた。
だったら、自分で道を切り開くのみである。
というわけで、以下アノテーションについてまとめてみた。
以下の方法を理解する。
最小限の学習ですむように説明するならば、 たとえば、
StringValueAnnotation
というアノテーションを作りたいとすると下記のようになる。
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @interface StringValueAnnotation { String value() default "デフォルト値"; }
その他は、固定値だと思って差しつかえない。
上記の例でTYPEとなっている箇所を
FIELD
に置き換えるだけでよい。
知りたいのは、実装するクラスの一覧であるが、どういうわけか Javaらしからず、そのような一覧取得のメソッドは用意されていない、 自分で道を切り開くのみである。
ソースフォルダを指定すると、クラス一覧を取得するメソッドを作製する。
package kuniwiki; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @interface ActionAnnotation { String value1() default ""; String value2() default ""; String value3() default ""; }
package kuniwiki; import java.io.File; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; public class AnnoMain { public static void main(String[] args) throws IOException { String basePath = "C:/bin/pleiades/workspace/prjAno/src"; FileSearch search = new FileSearch(); File[] files = search.listFiles(basePath, "*.java"); for(File f : files){ Class clazz = toClass(basePath, files[4]); HashMap<String, HashMap<String, String>> ano = toAnoHash(clazz); if (ano != null) { System.out.println(ano.get("kuniwiki.ActionAnnotation").get("value1")); System.out.println(ano.get("kuniwiki.ActionAnnotation").get("value2")); System.out.println(ano.get("kuniwiki.ActionAnnotation").get("value3")); } } } private static HashMap toAnoHash(Class clazz) { HashMap ret = new HashMap<String, HashMap<String, String>>(); Annotation[] as = clazz.getDeclaredAnnotations(); for (Annotation a : as) { Class tp = a.annotationType(); // アノテーション名を登録; HashMap<String, String> item = new HashMap<String, String>(); ret.put(a.annotationType().getName(), item); // フィールドを追加 ActionAnnotation an = (ActionAnnotation)a; //tp.getTypeParameters(); Method[] ms = an.getClass().getMethods(); //Annotation[][] ma = ms[0].getParameterAnnotations(); try { Object[] param = {}; item.put(ms[4].getName(),ms[4].invoke(an, param).toString()); } catch (IllegalArgumentException e) { // TODO e.printStackTrace(); } catch (IllegalAccessException e) { // TODO e.printStackTrace(); } catch (InvocationTargetException e) { // TODO e.printStackTrace(); } // item.put("value1",Class.forName("kuniwiki.ActionAnnotation").cast(a).getClass().getFields()[0].toString()); } return ret; } private static boolean hasActionAnnotation(Class clazz) { Class ano = ActionAnnotation.class; Annotation[] as = clazz.getDeclaredAnnotations(); for (Annotation a : as) { if (a instanceof ActionAnnotation) { return true; } } return false; } private static Class toClass(String src, File fi) { // ソースのパスを置換用に置き換える String srcpath = src.replaceAll("/", "\\\\\\\\"); // ファイルの親パスからソースパスをさっぴいて、フォルダを意味する記号をドットに置き換え、ファイル名をクラス名として連結する。 String classname = fi.getParent().replaceFirst(srcpath, "") .replaceAll("\\\\", ".").replaceFirst("\\.", "") + "." + fi.getName().replace(".java", ""); try { System.out.println(classname); return Class.forName(classname); } catch (ClassNotFoundException e) { return null; } } }
http://sattontanabe.blog86.fc2.com/blog-entry-55.html
http://www.ne.jp/asahi/hishidama/home/tech/java/annotation.html