前言
对于Java的相关知识推荐阅读:java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
1. 基本知识
@AliasFor
注解是 Spring 框架中的一个元注解,用于声明注解中属性之间的别名关系
其基本的属性如下:
value
:被指定为别名的属性的名称
通常情况下,value 属性是必须的,但在某些情况下也可以省略,例如当只有一个属性时attribute
:被指定为别名的属性的名称,与 value 属性一样,用于指定被别名的属性annotation
:指定目标注解的类型
如果未显式指定,将使用当前注解类型作为目标注解annotationType
:与 annotation 属性类似,指定目标注解的类型
先看其源码:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface AliasFor {
/**
* Alias for {@link #attribute}.
* <p>Intended to be used instead of {@link #attribute} when {@link #annotation}
* is not declared — for example: {@code @AliasFor("value")} instead of
* {@code @AliasFor(attribute = "value")}.
*/
@AliasFor("attribute")
String value() default "";
/**
* The name of the attribute that <em>this</em> attribute is an alias for.
* @see #value
*/
@AliasFor("value")
String attribute() default "";
/**
* The type of annotation in which the aliased {@link #attribute} is declared.
* <p>Defaults to {@link Annotation}, implying that the aliased attribute is
* declared in the same annotation as <em>this</em> attribute.
*/
Class<? extends Annotation> annotation() default Annotation.class;
}
主要的细节解读如下:
-
单注解中的显示别名
方式:在单个注解中,使用@AliasFor
在一对属性上声明它们是可互换的别名
作用:使用注解时,可以使用其中一个属性来指定值,而另一个属性将自动地具有相同的值 -
单个注解中的隐式别名:
方式:一个或多个属性被声明为相同的元注解属性的属性覆盖,那么将被视为一组隐式别名
作用:使用时具有相同的行为,类似于显式别名的情况 -
在元注解中对属性进行显式别名:
方式:annotation
属性指定了一个不同的注解类型,那么这个属性被解释为元注解中属性的别名
作用:在注解层次结构中精细地控制哪些属性被覆盖
2. Demo
结合Demo方便理解
- 显式别名:
每个属性都必须使用 @AliasFor 进行注解,而且这些属性必须引用同一个元注解中的相同属性,可以是直接引用,也可以通过注解层次结构中其他显式的元注解属性间接引用
别名属性必须声明相同的返回类型和默认值
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AliasFor;
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
// value 和 basePackages 是隐式的别名
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] value() default {};
}
- 元注解中的显式别名
import org.springframework.test.context.ContextConfiguration;
import org.springframework.core.annotation.AliasFor;
@MyTestConfig
public class MyTest {
// MyTestConfig 注解中的 groovyScripts 是 @ContextConfiguration 注解中的 locations 的别名
@ContextConfiguration(locations = "test.xml")
@interface MyTestConfig {
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] groovyScripts() default {};
}
}
- 隐式别名
在 @MyTestConfig 注解中,value、groovyScripts 和 xmlFiles 都是对 @ContextConfiguration 中 locations 属性的显式元注解属性覆盖
import org.springframework.test.context.ContextConfiguration;
import org.springframework.core.annotation.AliasFor;
@MyTestConfig
public class MyTest {
// MyTestConfig 注解中的 value, groovyScripts 和 xmlFiles 都是隐式的别名
@ContextConfiguration(locations = "test.xml")
@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 {};
}
}
- 传递性隐式别名
在 @GroovyOrXmlTestConfig 注解中,groovy 是对 @MyTestConfig 中 groovyScripts 属性的显式覆盖,而 xml 是对 @ContextConfiguration 中 locations 属性的显式覆盖
import org.springframework.test.context.ContextConfiguration;
import org.springframework.core.annotation.AliasFor;
@MyTestConfig
public class MyTest {
// GroovyOrXmlTestConfig 注解中的 groovy 是对 MyTestConfig 注解中的 groovyScripts 的显式覆盖
// GroovyOrXmlTestConfig 注解中的 xml 是对 @ContextConfiguration 注解中的 locations 的显式覆盖
// 因为它们都覆盖了 @ContextConfiguration 中的 locations,所以 groovy 和 xml 是传递性的隐式别名
@GroovyOrXmlTestConfig
@interface MyTestConfig {
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] groovyScripts() default {};
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] xmlFiles() default {};
}
@MyTestConfig
@interface GroovyOrXmlTestConfig {
@AliasFor(annotation = MyTestConfig.class, attribute = "groovyScripts")
String[] groovy() default {};
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] xml() default {};
}
}