java 注解反射实例

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的测试

猜你喜欢

转载自jarvi.iteye.com/blog/2277215