22.4 查看注解信息
创建了注解,就可以在程序中使用,注解指定的目标,提供需要的参数,但这还是不会影响到程序的运行。要影响程序,我们要先能查看这些信息。我们主要考虑@Retention为RetentionPolicy.RUNTIME的注解,利用反射机制在运行时进行查看和利用这些信息。
在上一章,我们提到了反射相关类中与注解有关的方法,这里汇总说明下,Class、Field、Method、Constructor中都有如下方法:
1 2 3 4 5 6 7 8 9
| public Annotation[] getAnnotations()
public Annotation[] getDeclaredAnnotations()
public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
public boolean isAnnotationPresent( Class<? extends Annotation> annotationClass)
|
Annotation是一个接口,它表示注解,具体定义为:
1 2 3 4 5 6 7
| public interface Annotation { boolean equals(Object obj); int hashCode(); String toString(); Class<? extends Annotation> annotationType(); }
|
实际上,内部实现时,所有的注解类型都是扩展的Annotation。
对于Method和Contructor,它们都有方法参数,而参数也可以有注解,所以它们都有如下方法:
1
| public Annotation[][] getParameterAnnotations()
|
返回值是一个二维数组,每个参数对应一个一维数组。我们看个简单的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class MethodAnnotations { @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) static @interface QueryParam { String value(); } @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) static @interface DefaultValue { String value() default ""; } public void hello(@QueryParam("action") String action, @QueryParam("sort") @DefaultValue("asc") String sort){ } public static void main(String[] args) throws Exception { Class<? > cls = MethodAnnotations.class; Method method = cls.getMethod("hello", new Class[]{String.class, String.class}); Annotation[][] annts = method.getParameterAnnotations(); for(int i=0; i<annts.length; i++){ System.out.println("annotations for paramter " + (i+1)); Annotation[] anntArr = annts[i]; for(Annotation annt : anntArr){ if(annt instanceof QueryParam){ QueryParam qp = (QueryParam)annt; System.out.println(qp.annotationType() .getSimpleName()+":"+ qp.value()); }else if(annt instanceof DefaultValue){ DefaultValue dv = (DefaultValue)annt; System.out.println(dv.annotationType() .getSimpleName()+":"+ dv.value()); } } } } }
|
这里定义了两个注解@QueryParam
和@DefaultValue
,都用于修饰方法参数,方法hello使用了这两个注解,在main方法中,我们演示了如何获取方法参数的注解信息,输出为:
1 2 3 4 5
| annotations for paramter 1 QueryParam:action annotations for paramter 2 QueryParam:sort DefaultValue:asc
|
代码比较简单,就不赘述了。
定义了注解,通过反射获取到注解信息,但具体怎么利用这些信息呢?我们看两个简单的示例,一个是定制序列化,另一个是DI(依赖注入)容器。