Java注解反射实例
主要功能:
1. 得到一个类的所有注解信息
2. 通过注解信息实例化一个类
实体类:
1. 注解类
import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到 @Target({ElementType.FIELD,ElementType.METHOD})//定义注解的作用目标**作用范围字段、枚举的常量/方法 @Documented //说明该注解将被包含在javadoc中 public @interface FieldMeta { /** * 是否国序列号 * @return */ boolean id() default false; /** * 字段名称 * @return */ String name() default ""; /** * 值 * @return */ String value() default ""; /** * 字段描述 * @return */ String description() default ""; /** * 排序字段 * @return */ int order() default 0; }
2. 包含注解的实体类
import java.util.Date; public class Anno { @FieldMeta(id=true,name="序列号",value="1",order=1) private int id; @FieldMeta(name="姓名",value="Matt",order=3) private String name; @FieldMeta(name="年龄",value="12",order=2) private int age; @FieldMeta(name="出生日期",value="1999-08-12 12:12:12",order=4) private Date date; public Anno() { super(); } public Anno(int id, String name, int age) { super(); this.id = id; this.name = name; this.age = age; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } @FieldMeta(description="描述",order=4) public String desc(){ return "java反射获取annotation的测试"; } @Override public String toString() { return "Anno [id=" + id + ", name=" + name + ", age=" + age + ", date=" + date + "]"; } }
3. 处理注解的类
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; public abstract class BasicAnnoHannlder<T> { private Class<T> entity; private String dateFormat = "yyyy-MM-dd HH:mm:ss"; public BasicAnnoHannlder(){} /** * 实例化T对象 * @return */ public T init2(){ entity = (Class<T>) ((ParameterizedType)this.getClass().getGenericSuperclass()) .getActualTypeArguments()[0]; try { //得到构造方法得到对象并赋值 Constructor<T> constructor = entity.getConstructor(); T instance = constructor.newInstance(); setFilds(instance); return instance; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 得到所有的注解信息 * @return */ @SuppressWarnings("unchecked") public List<SortableField> init(){ List<SortableField> list = new ArrayList<SortableField>(); /**getClass().getGenericSuperclass()返回表示此 Class 所表示的实体(类、接口、基本类型或 void) * 的直接超类的 Type(Class<T>泛型中的类型),然后将其转换ParameterizedType。。 * getActualTypeArguments()返回表示此类型实际类型参数的 Type 对象的数组。 * [0]就是这个数组中第一个了。。 * 简而言之就是获得超类的泛型参数的实际类型。。*/ entity = (Class<T>)((ParameterizedType)this.getClass().getGenericSuperclass()) .getActualTypeArguments()[0]; if(this.entity!=null){ /**返回类中所有字段,包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段 * entity.getFields();只返回对象所表示的类或接口的所有可访问公共字段 * 在class中getDeclared**()方法返回的都是所有访问权限的字段、方法等; * 可看API * */ Field[] fields = entity.getDeclaredFields(); // for(Field f : fields){ //获取字段中包含fieldMeta的注解 FieldMeta meta = f.getAnnotation(FieldMeta.class); if(meta!=null){ //System.out.println(meta+"\tName:" + f.getName() + "\tType:" + f.getType()); SortableField sf = new SortableField(meta, f); list.add(sf); } } //返回对象所表示的类或接口的所有可访问公共方法 Method[] methods = entity.getMethods(); for(Method m:methods){ FieldMeta meta = m.getAnnotation(FieldMeta.class); if(meta!=null){ //System.out.println(meta + "\tName:" + m.getName() +"\tType:"+ m.getReturnType()); SortableField sf = new SortableField(meta,m.getName(),m.getReturnType()); list.add(sf); } } //这种方法是新建FieldSortCom类实现Comparator接口,来重写compare方法实现排序 Collections.sort(list, new Comparator<SortableField>() { public int compare(SortableField s1,SortableField s2) { return s1.getMeta().order()-s2.getMeta().order(); // return s1.getName().compareTo(s2.getName());//也可以用compare来比较 } }); } return list; } private T setFilds(T t) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ParseException{ Field[] fields = t.getClass().getDeclaredFields(); // 获取实体类的所有属性,返回Field数组 for(int i=0;i < fields.length;i++){ // 遍历所有属性 String name = fields[i].getName(); // 获取属性的名字 name = name.substring(0, 1).toUpperCase() + name.substring(1); // 将属性的首字符大写,方便构造get,set方法 String type = fields[i].getGenericType().toString(); //获取属性的类型 String value = fields[i].getAnnotation(FieldMeta.class).value(); //获取属性注解的value值 //根据类型反射给field赋值 if(type.equals("class java.lang.String")){ Method m = t.getClass().getMethod("set"+name,String.class); m.invoke(t, value); } else if (type.equals("class java.lang.Integer")) { Method m = t.getClass().getMethod("set"+name,Integer.class); m.invoke(t, Integer.parseInt(value)); } else if(type.equals("int")){ Method m = t.getClass().getMethod("set"+name,int.class); m.invoke(t, (int)Integer.parseInt(value)); } else if(type.equals("class java.util.Date")){ Method m = t.getClass().getMethod("set"+name,Date.class); Date date = new SimpleDateFormat(dateFormat).parse(value); m.invoke(t, date); } // 如果有需要,可以仿照上面继续进行扩充,再增加对其它类型的判断 } return t; } }
4. 处理注解的子类
//传递Anno.class给父类 public class AnnoHannlder extends BasicAnnoHannlder<Anno>{ }
5. 保存注解信息的类
import java.lang.reflect.Field; public class SortableField { private FieldMeta meta; private Field field; private String name; private Class<?> type; public SortableField() {} public SortableField(FieldMeta meta, Field field) { super(); this.meta = meta; this.field = field; } public SortableField(FieldMeta meta,String name, Class<?> type) { super(); this.meta = meta; this.name = name; this.type = type; } public FieldMeta getMeta() { return meta; } public void setMeta(FieldMeta meta) { this.meta = meta; } public Field getField() { return field; } public void setField(Field field) { this.field = field; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Class<?> getType() { return type; } public void setType(Class<?> type) { this.type = type; } @Override public String toString() { return "SortableField [meta=" + meta + ", field=" + field + ", name=" + name + ", type=" + type + "]"; } }
6. 测试类
import java.util.List; public class TestAnnotation { public static void main(String[] args) { BasicAnnoHannlder<Anno> c = new AnnoHannlder(); List<SortableField> list = c.init();//获取泛型中类里面的注解 //输出结果 for(SortableField l : list){ System.out.println(l); } //通过注解得到对象 Anno anno = c.init2(); System.out.println(anno+ "\n"+ anno.desc()); } }
测试结果:
SortableField [[email protected](summary=true, editable=true, name=序列号, description=, id=true, value=1, order=1), field=private int com.gson.demo.anno.Anno.id, name=null, type=null] SortableField [[email protected](summary=true, editable=true, name=年龄, description=, id=false, value=12, order=2), field=private int com.gson.demo.anno.Anno.age, name=null, type=null] SortableField [[email protected](summary=true, editable=true, name=姓名, description=, id=false, value=Matt, order=3), field=private java.lang.String com.gson.demo.anno.Anno.name, name=null, type=null] SortableField [[email protected](summary=true, editable=true, name=出生日期, description=, id=false, value=1999-08-12 12:12:12, order=4), field=private java.util.Date com.gson.demo.anno.Anno.date, name=null, type=null] SortableField [[email protected](summary=true, editable=true, name=, description=描述, id=false, value=, order=4), field=null, name=desc, type=class java.lang.String] Anno [id=1, name=Matt, age=12, date=Thu Aug 12 12:12:12 CST 1999] java反射获取annotation的测试