JAVA EE那些事儿JAVA学习

你了解注解内的@interface List么

2015-11-22  本文已影响790人  曲水流觞TechRill

Annotation, Multi-valued annotation, nested annotation, 多值注解, 嵌套注解

今天在研究Spring MVC的Validation机制时(这里 | 还有这里),简单看了下一些注解的源码,比如@Min,发现以前从来没注意到的注解写法。看来基础知识有疏漏啊...

/**
 * Validate a zipcode for a given country 
 * The only supported type is String
  */
 @Documented
 @Constraint(validatedBy = ZipCodeValidator.class)
 @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR,      PARAMETER })
 @Retention(RUNTIME)
 public @interface ZipCode {
     String countryCode();
     String message() default "{com.acme.constraint.ZipCode.message}";
     Class<?>[] groups() default {};
     Class<? extends Payload>[] payload() default {};
     /**
      * Defines several @ZipCode annotations on the same element
      * @see (@link ZipCode}
      */
     @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
     @Retention(RUNTIME)
     @Documented
     @interface List {
         ZipCode[] value();
     }    
 }

这是一个对邮政编码进行验证的一个注解,注解内又好像多了个类似内部类一样的内部注解(自己造的术语_),或者说嵌套注解, 先说这个注解的用法

public class Address {
    @ZipCode.List( {
        @ZipCode(countryCode="fr", groups=Default.class
                 message = "zip code is not valid"),
        @ZipCode(countryCode="fr", groups=SuperUser.class
                 message = "zip code invalid. Requires overriding before saving.")
        } )
    private String zipcode;
}

总结一下,这类注解的作用是解决Java不支持多重重复注解问题的,比如如下的重复注解是编译不过的!

@Metadata(name="size (KB)", value="1024")
@Metadata(name="size (MB)", value="1")
@Test
public void myPerfTest(){ // do stuff}

javac 编译输出:
./org/junitbench/examples/MetadataTest.java:[23, 18] duplicate annotation

另外,Java反射API不支持根据名字来获取多个注解
(see: java.lang.reflect.AnnotatedElement.getAnnotation(…)). 如果语义上显性支持的话我们就可以在注解的过滤器中获取到这些信息了。但既然Java不支持,那我们就需要寻求一个替代方案。通过定义一个封装的注解类型,让它可以接受不限数量的嵌入注解即可。

@Metadata(
{
     @Data(name="size (KB)", value="1024"), 
     @Data(name="size (MB)", value="1")
})
@Test 
public void myPerfTest(){ // do stuff}```

该注解是这样定义的:

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({})
public @interface Data{
String name();
String value();
}```

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Metadata{ 
  Data[] value();
}

该用法的重点就是内部嵌入的注解是作为集合的形式出现(数组或者文章最开始的List均可实现)。

Reference:
https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations

上一篇 下一篇

猜你喜欢

热点阅读