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 [meta=@com.gson.demo.anno.FieldMeta(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 [meta=@com.gson.demo.anno.FieldMeta(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 [meta=@com.gson.demo.anno.FieldMeta(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 [meta=@com.gson.demo.anno.FieldMeta(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 [meta=@com.gson.demo.anno.FieldMeta(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的测试