Annotation, Multi-valued annotation, nested annotation, 多值注解, 嵌套注解
今天在研究Spring MVC的Validation機(jī)制時(shí)(這里 | 還有這里),簡(jiǎn)單看了下一些注解的源碼,比如@Min,發(fā)現(xiàn)以前從來(lái)沒(méi)注意到的注解寫(xiě)法。看來(lái)基礎(chǔ)知識(shí)有疏漏啊...
/**
* 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();
}
}
這是一個(gè)對(duì)郵政編碼進(jìn)行驗(yàn)證的一個(gè)注解,注解內(nèi)又好像多了個(gè)類(lèi)似內(nèi)部類(lèi)
一樣的內(nèi)部注解
(自己造的術(shù)語(yǔ)_),或者說(shuō)嵌套注解, 先說(shuō)這個(gè)注解的用法
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;
}
總結(jié)一下,這類(lèi)注解的作用是解決Java不支持多重重復(fù)注解問(wèn)題的,比如如下的重復(fù)注解是編譯不過(guò)的!
@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不支持根據(jù)名字來(lái)獲取多個(gè)注解
(see: java.lang.reflect.AnnotatedElement.getAnnotation(…)). 如果語(yǔ)義上顯性支持的話我們就可以在注解的過(guò)濾器中獲取到這些信息了。但既然Java不支持,那我們就需要尋求一個(gè)替代方案。通過(guò)定義一個(gè)封裝的注解類(lèi)型,讓它可以接受不限數(shù)量的嵌入注解即可。
@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();
}
該用法的重點(diǎn)就是內(nèi)部嵌入的注解是作為集合的形式出現(xiàn)(數(shù)組或者文章最開(kāi)始的List均可實(shí)現(xiàn))。
Reference:
https://blogs.oracle.com/toddfast/entry/creating_nested_complex_java_annotations