目录
2.1、Explicit aliases within an annotation
2.2、Explicit alias for attribute in meta-annotation
2.3、Implicit aliases within an annotation
一、介绍
@AliaFor是一个用于声明注解属性别名的注解。可以让同一个注解里的两个属性成为一个属性,两者互为别名,也可以覆盖元注解的属性。下面是他的定义:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface AliasFor {
@AliasFor("attribute")
String value() default "";
@AliasFor("value")
String attribute() default "";
Class<? extends Annotation> annotation() default Annotation.class;
}
有三个属性,value和attribute互为别名,下面是它的api文档说明:
Modifier and Type | Optional Element and Description |
---|---|
java.lang.Class<? extends java.lang.annotation.Annotation> | annotation The type of annotation in which the aliased |
java.lang.String | attribute The name of the attribute that thisattribute is an alias for. |
java.lang.String | value Alias for |
value和attribute指定一个属性名,而被@AliasFor注解的属性名为该属性的别名。比如value是attribute的别名,attribute是value的别名。
二、使用
2.1、Explicit aliases within an annotation
- Each attribute that makes up an aliased pair must be annotated with
@AliasFor
, and eitherattribute()
orvalue()
must reference the other attribute in the pair. - Aliased attributes must declare the same return type.
- Aliased attributes must declare a default value.
- Aliased attributes must declare the same default value.
annotation()
should not be declared.
意思就是同一个注解内可以相互声明别名,下面声明一个@ContextConfiguration
public @interface ContextConfiguration {
@AliasFor("locations")
String[] value() default {};
@AliasFor("value")
String[] locations() default {};
// ...
}
然后value和location互为别名,注意返回类型和默认值要一致。
2.2、Explicit alias for attribute in meta-annotation
- The attribute that is an alias for an attribute in a meta-annotation must be annotated with
@AliasFor
, andattribute()
must reference the attribute in the meta-annotation. - Aliased attributes must declare the same return type.
annotation()
must reference the meta-annotation.- The referenced meta-annotation must be meta-present on the annotation class that declares
@AliasFor
.
通过aliasfor来覆盖元注解的属性,此时不需要默认值了,但需要使用annotation指定元注解,下面声明@XmlTestConfig
@ContextConfiguration
public @interface XmlTestConfig {
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] xmlFiles();
}
声明了@ContextConfiguration的locations属性,此时可以通过@XmlTestConfig的xmlFiles来为@ContextConfiguration的locations赋值。
下面看一个spring文档中的一个例子1.10.2. Meta-annotations
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Scope(WebApplicationContext.SCOPE_SESSION)
public @interface SessionScope {
@AliasFor(annotation = Scope.class)
ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}
上面第一点说到,必须要使用attribute来指明覆盖的属性,但是这里没有使用,我猜它会自己主动在元注解中找同名的属性吧。
2.3、Implicit aliases within an annotation
- Each attribute that belongs to a set of implicit aliases must be annotated with
@AliasFor
, andattribute()
must reference the same attribute in the same meta-annotation (either directly or transitively via other explicit meta-annotation attribute overrides within the annotation hierarchy). - Aliased attributes must declare the same return type.
- Aliased attributes must declare a default value.
- Aliased attributes must declare the same default value.
annotation()
must reference an appropriate meta-annotation.- The referenced meta-annotation must be meta-present on the annotation class that declares
@AliasFor
.
就是说,同一个注解中的多个属性覆盖了元注解的一个相同的属性,此时,这些属性隐性的互为别名了,注意属性覆盖的传递性。
下面看一个声明:
@ContextConfiguration
public @interface MyTestConfig {
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] value() default {};
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] groovyScripts() default {};
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] xmlFiles() default {};
}
此刻,三个属性同时是元注解locations的别名,那么这三个属性隐性互为别名。
下面看看隐性传递的例子:
@MyTestConfig
public @interface GroovyOrXmlTestConfig {
@AliasFor(annotation = MyTestConfig.class, attribute = "groovyScripts")
String[] groovy() default {};
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] xml() default {};
}
属性覆盖具有传递性,因此这两个属性最终覆盖了@ContextConfiguration的locations属性,因此这两个属性互为别名。