Java 注解的读取注解信息的方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 注解的读取注解信息的方法相关的知识,希望对你有一定的参考价值。

属于重点,在系统中用到注解权限时非常有用,可以精确控制权限的粒度
注意:要想使用反射去读取注解,必须将Retention的值选为Runtime Java代码import java.lang.annotation.Annotation;import java.lang.reflect.Method;//读取注解信息public class ReadAnnotationInfoTest     public static void main(String[] args) throws Exception         // 测试AnnotationTest类,得到此类的类对象        Class c = Class.forName(com.iwtxokhtd.annotation.AnnotationTest);        // 获取该类所有声明的方法        Method[] methods = c.getDeclaredMethods();        // 声明注解集合        Annotation[] annotations;        // 遍历所有的方法得到各方法上面的注解信息        for (Method method : methods)             // 获取每个方法上面所声明的所有注解信息            annotations = method.getDeclaredAnnotations();            // 再遍历所有的注解,打印其基本信息            System.out.println(method.getName());            for (Annotation an : annotations)                 System.out.println(方法名为: + method.getName() + 其上面的注解为: + an.annotationType().getSimpleName());                Method[] meths = an.annotationType().getDeclaredMethods();                // 遍历每个注解的所有变量                for (Method meth : meths)                     System.out.println(注解的变量名为: + meth.getName());                                        

参考技术A @Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Target(ElementType.FIELD,ElementType.METHOD)//定义注解的作用目标**作用范围字段、枚举的常量/方法
@Documented//说明该注解将被包含在javadoc中
public @interface FieldMeta

/**
* 是否为序列号
* @return
*/
boolean id() default false;
/**
* 字段名称
* @return
*/
String name() default "";
/**
* 是否可编辑
* @return
*/
boolean editable() default true;
/**
* 是否在列表中显示
* @return
*/
boolean summary() default true;
/**
* 字段描述
* @return
*/
String description() default "";
/**
* 排序字段
* @return
*/
int order() default 0;


实体类:

[java] view plain copy print?
public class Anno

@FieldMeta(id=true,name="序列号",order=1)
private int id;
@FieldMeta(name="姓名",order=3)
private String name;
@FieldMeta(name="年龄",order=2)
private int age;

@FieldMeta(description="描述",order=4)
public String desc()
return "java反射获取annotation的测试";


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;




获取到注解的帮助类:

[java] view plain copy print?
public class SortableField

public SortableField()

public SortableField(FieldMeta meta, Field field)
super();
this.meta = meta;
this.field = field;
this.name=field.getName();
this.type=field.getType();


public SortableField(FieldMeta meta, String name, Class<?> type)
super();
this.meta = meta;
this.name = name;
this.type = type;


private FieldMeta meta;
private Field field;
private String name;
private Class<?> 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;




运行时获取注解,首先创建一个基类:

[java] view plain copy print?
public class Parent<T>

private Class<T> entity;

public Parent()
init();


@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];
// FieldMeta filed = entity.getAnnotation(FieldMeta.class);

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)
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)
SortableField sf = new SortableField(meta,m.getName(),m.getReturnType());
list.add(sf);


//这种方法是新建FieldSortCom类实现Comparator接口,来重写compare方法实现排序
// Collections.sort(list, new FieldSortCom());
Collections.sort(list, new Comparator<SortableField>()
@Override
public int compare(SortableField s1,SortableField s2)
return s1.getMeta().order()-s2.getMeta().order();
// return s1.getName().compareTo(s2.getName());//也可以用compare来比较


);

return list;



创建子类继承基类:

[java] view plain copy print?
public class Child extends Parent<Anno>



测试类:

[java] view plain copy print?
public class TestAnnotation

@SuppressWarnings( "unchecked", "rawtypes" )
public static void main(String[] args)
Parent c = new Child();
List<SortableField> list = c.init();//获取泛型中类里面的注解
//输出结果
for(SortableField l : list)
System.out.println("字段名称:"+l.getName()+"\t字段类型:"+l.getType()+
"\t注解名称:"+l.getMeta().name()+"\t注解描述:"+l.getMeta().description());


java注解和反射

2020-05-19

注解的作用:

不是程序本身,可以对程序做出解释,和注释有相似之处。
可以被其他程序(如编译器)所读取。
注解的格式:以“@注解名”在代码上存在,还可以在其中添加一些参数。

注解在哪里使用:可以附在包,类,方法,字段上面。等于给他们添加了额外的辅助信息。我们可以通过反射机制实现对这些元数据的访问。

注解举例:

@override:重写的注解
@Deprecated:过时的注解
元注解:对注解的注解。有如下四类元注解。

@Target:用于描述注解的使用范围(即被描述的注解可以用在什么地方)
@Retention:表示需要在什么级别保存注释信息,用于描述注解的生命周期(source>class>runtime)
@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解
自定义注解:使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口

@interface用来声明一个注解,格式:public @interface 注解名{定义内容}

其中的每一个方法实际是声明了一个配置参数

方法的名称就是参数的名称

返回值类型就是参数的类型(返回值只能是基本类型,Class,String,enum)

可以通过default来声明参数的默认值

如果只有一个参数成员,一般参数为value

注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0作为默认值。

以上是关于Java 注解的读取注解信息的方法的主要内容,如果未能解决你的问题,请参考以下文章

Java annotation (注解)

反射读取注解信息

java 获取所有带注解的类

java注解

java注解

java注解和反射