java中的meta-annotation
练习,根据对类的声明初始化对象,并根据输入初始化对应的属性
Info.java
1 import java.lang.annotation.*; 2 3 @Target(ElementType.TYPE) 4 @Retention(RetentionPolicy.RUNTIME) 5 @Documented 6 public @interface Info { 7 String[] fields(); 8 }
InitUtil.java
1 import java.lang.reflect.*; 2 3 public class InitUtil { 4 5 public static <T> T initObj(Class<T> c, final Object... values) { 6 String[] fl= c.getAnnotation(Info.class).fields();//use meta-annotation 7 Field[] fs = c.getDeclaredFields(); 8 T obj = null; 9 try { 10 obj = c.newInstance(); 11 int index = 0; 12 for (Field f : fs) { 13 f.setAccessible(true); 14 if(f.getName().equals(fl[index])) { 15 f.set(obj, values[index]); 16 index++; 17 } 18 } 19 } catch (Exception e) { 20 return null; 21 } 22 return obj; 23 } 24 25 }
Person.java
1 @Info(fields = {"name","age","gender"}) 2 public class Person { 3 4 private String name; 5 private int age; 6 private boolean gender; 7 public String getName() { 8 return name; 9 } 10 public void setName(String name) { 11 this.name = name; 12 } 13 public int getAge() { 14 return age; 15 } 16 public void setAge(int age) { 17 this.age = age; 18 } 19 public boolean getGender() { 20 return gender; 21 } 22 public void setGender(boolean gender) { 23 this.gender = gender; 24 } 25 }
Test:
1 public static void main(String[] args) { 2 Person p; 3 p=InitUtil.initObj(Person.class, "qwerty", 12, true);//call custom init 4 System.out.println(p.getName()+p.getAge()+p.getGender()); 5 }
练习,根据对域的声明初始化对应域
InitAuto.java
1 import java.lang.annotation.*; 2 3 @Target(ElementType.FIELD) 4 @Retention(RetentionPolicy.RUNTIME) 5 @Documented 6 public @interface InitAuto { 7 8 }
InitUtil.java
1 import java.lang.reflect.*; 2 3 public class InitUtil { 4 5 public static void initObj(Object o) { 6 Class<?> c = o.getClass(); 7 Field[] fs = c.getDeclaredFields(); 8 for(Field f : fs) { 9 if(f.isAnnotationPresent(InitAuto.class)) {//get field annotated by InitAuto 10 f.setAccessible(true); 11 try { 12 Class<?> cc = f.getType(); 13 if(cc.getName().endsWith("Person")) { 14 Object obj = cc.newInstance();//init Person 15 Field ff = cc.getDeclaredField("name"); 16 ff.setAccessible(true); 17 ff.set(obj, "test name");//set custom properties 18 f.set(o, obj); 19 } else { 20 //other type of field 21 } 22 } catch (Exception e) { 23 e.printStackTrace(); 24 } 25 } else { 26 //other type of annotation 27 } 28 } 29 } 30 }
Person.java
same as above
Group.java
1 public class Group { 2 @InitAuto 3 private Person p1; 4 @InitAuto 5 private Object o1; 6 7 public Person getP1() { 8 return p1; 9 } 10 public Object getO1() { 11 return o1; 12 } 13 }
Test:
1 public static void main(String[] args) { 2 Group ps = new Group(); 3 InitUtil.initObj(ps);//真正实现的时候使用decorator模式 4 System.out.println(ps.getP1().getName()+ps.getO1()); 5 }
练习,根据注释调用方法
DataSource.java
1 import java.lang.annotation.*; 2 3 @Target(ElementType.METHOD) 4 @Retention(RetentionPolicy.RUNTIME) 5 @Documented 6 public @interface DataSource { 7 String source(); 8 }
DataPattern.java
1 import java.lang.annotation.*; 2 3 @Target(ElementType.PARAMETER) 4 @Retention(RetentionPolicy.RUNTIME) 5 @Documented 6 public @interface DataPattern { 7 String value() default "";//you can use DataPattern("...") if you declare value() property 8 }
InitUtil.java
1 import java.lang.reflect.*; 2 3 public class InitUtil { 4 5 public static void initMtd(Object o) { 6 Class<?> c = o.getClass(); 7 Method[] ms = c.getDeclaredMethods(); 8 for(Method m : ms) { 9 if(m.isAnnotationPresent(DataSource.class)) { 10 m.setAccessible(true); 11 12 //the first parameter is annotated to set the pattern 13 DataPattern p = m.getParameters()[0].getAnnotation(DataPattern.class); 14 String dataPattern = p.value(); 15 //the method is annotated to set the data source 16 String dataSource = m.getAnnotation(DataSource.class).source(); 17 18 /*do something to listen to the data source*/ 19 20 try { 21 m.invoke(o, dataSource+"->"+dataPattern, 22 new java.util.concurrent.ConcurrentHashMap<String,String>()); 23 } catch (Exception e) { 24 e.printStackTrace(); 25 } 26 } 27 } 28 } 29 }
Action.java
1 public class Action { 2 @DataSource(source = "page") 3 public String excute(@DataPattern("data") String d , java.util.Map<String,String> m) { 4 System.out.println(d); 5 m.put("data", d+" in map"); 6 System.out.println(m.get("data")); 7 return ""; 8 } 9 }
Test
1 public static void main(String[] args) { 2 Action a = new Action(); 3 InitUtil.initMtd(a); 4 }