我们知道SpringMVC框架都是运用注解注入,那么我们怎么获取标有注解的类或方法呢?我们可以运用java反射机制获取注解的类然后进行类解析机制获取到这个类的所有属性。
首先我们要明白java5.0后有几种注解方式
元注解:
元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:
1.@Target,
2.@Retention,
3.@Documented,
4.@Inherited
这些类型和它们所支持的类在java.lang.annotation包中可以找到。下面我们看一下每个元注解的作用和相应分参数的使用说明。
@Target 表示该注解用于什么地方,可能的值在枚举类 ElemenetType 中,包括:
ElemenetType.CONSTRUCTOR 构造器声明
ElemenetType.FIELD 域声明(包括 enum 实例)
ElemenetType.LOCAL_VARIABLE 局部变量声明
ElemenetType.ANNOTATION_TYPE 作用于注解量声明
ElemenetType.METHOD 方法声明
ElemenetType.PACKAGE 包声明
ElemenetType.PARAMETER 参数声明
ElemenetType.TYPE 类,接口(包括注解类型)或enum声明
@Retention 表示在什么级别保存该注解信息。可选的参数值在枚举类型 RetentionPolicy 中,包括:
RetentionPolicy.SOURCE 注解将被编译器丢弃
RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃
RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。
@Documented 将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。相当与@see,@param 等。
@Inherited 允许子类继承父类中的注解,例子中补充。
那么接下来我们来手动创建自定义注解
package com.example.demo.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 类注解
* @author xiaoyu
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface CETypeAnnotation {
public int id() default 0;
}
我们创建了一个类注解@Target是声明这个注解是一个类注解,@Retention是声明这个注解是在类加载的时候可以被java反射机制获取到,这个注解有一个id属性.
接下来我们分别创建一个构造器注解、方法注解、方法参数注解、属性注解等。
/**
* 构造方法注解
* @author xiaoyu
*/
@Target(ElementType.CONSTRUCTOR)
@Retention(RetentionPolicy.RUNTIME)
public @interface CEConstructorAnnotation {
public String value() default "";
}
/**
* 方法注解
* @author xiaoyu
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CEMethodAnnotation {
String description() default "";
}
/**
* 方法参数注解
* @author xiaoyu
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CEParameterAnnotation {
public String value() default "";
}
/**
* 字段注解
* @author xiaoyu
*
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CEfileldAnnotation {
public String value() default "";
}
接下来我们要创建一个实体类并在类中运用自定义注解,
@CETypeAnnotation(id = 10)
public class TestEntity {
@CEfileldAnnotation(value = "成员属性注解")
public String value;
@CEfileldAnnotation(value = "成员属性注解2")
public String value2;
@CEConstructorAnnotation(value="构造方法注解")
public TestEntity() {}
@CEMethodAnnotation(description = "成员方法注解")
public void method1(@CEParameterAnnotation(value="方法参数注解") String parameter,@CEParameterAnnotation(value="方法参数注解2") String parameter2){
}
}
然后接下来我们要创建一个注解解析类运用java反射获取到这个类中的所有注解:
public class AnnotationTracker {
public static void trackTypeAnnotation(Class> cl){
//获取类注解
CETypeAnnotation ceTypeAnnotation = cl.getAnnotation(CETypeAnnotation.class);
if(ceTypeAnnotation != null){
System.out.println("类是"+ceTypeAnnotation.id());
}
//获取方法参数注解
CEParameterAnnotation ceParameterAnnotation = cl.getAnnotation(CEParameterAnnotation.class);
if(ceParameterAnnotation !=null){
System.out.println("方法的注解是"+ceParameterAnnotation.value());
}
}
public static void trackConstructorAnnotation(Class> cl){
//获取构造器注解
for(Constructor> constructor : cl.getConstructors()){
CEConstructorAnnotation ceConstructorAnnotation = constructor.getAnnotation(CEConstructorAnnotation.class);
if(ceConstructorAnnotation != null){
System.out.println("构造器是"+ceConstructorAnnotation.value());
}
}
}
public static void trackMethodAnnotation(Class> cl){
//获取方法注解
for(Method method : cl.getDeclaredMethods()){
CEMethodAnnotation ceMethodAnnotation = method.getAnnotation(CEMethodAnnotation.class);
if(ceMethodAnnotation!=null){
System.out.println("方法注解是"+ceMethodAnnotation.description());
}
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if(method.getParameterAnnotations().length > 0){
for(int i=0;i0];
System.out.println("方法参数注解是"+cEParameterAnnottation.value());
}
}
}
}
public static void trackFileldAnnotation(Class> cl){
//获取类属性注解
for(Field field : cl.getDeclaredFields()){
CEfileldAnnotation cEfileldAnnotation = field.getAnnotation(CEfileldAnnotation.class);
if(cEfileldAnnotation != null){
System.out.println("字段注解是"+cEfileldAnnotation.value());
}
}
}
}
我们来测试这个注解解析类可不可用,编写一个测试类:
public class AnnotationTestMain {
public static void main(String[] args) {
System.out.println("------加载类的注解解析器------");
AnnotationTracker.trackTypeAnnotation(TestEntity.class);
System.out.println("------加载类构造器注解解析器------");
AnnotationTracker.trackConstructorAnnotation(TestEntity.class);
System.out.println("------加载类方法注解解析器------");
AnnotationTracker.trackMethodAnnotation(TestEntity.class);
System.out.println("------加载类属性注解解析器------");
AnnotationTracker.trackFileldAnnotation(TestEntity.class);
}
}
运行得到:
——加载类的注解解析器——
类的值是10
——加载类构造器注解解析器——
构造器是构造方法注解
——加载类方法注解解析器——
方法注解是成员方法注解
方法参数是方法参数注解
方法参数是方法参数注解2
——加载类属性注解解析器——
字段是成员属性注解
字段是成员属性注解2