springboot 注解中@AliaFor的原理:
AliasFor的源码:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface AliasFor {
//作用就是给AliasFor注解的value属性起了一个别名叫做attribute,那么调用的时候调用 @AliasFor(attribute='123')那么value属性的值就是123
@AliasFor("attribute")
String value() default "";
//作用就是给AliasFor注解的attribute属性起了一个别名叫做value,那么调用的时候调用 @AliasFor(value='123')那么attribute属性的值就是123
@AliasFor("value")
String attribute() default "";
//元注解:默认是Annotation,作用是标明别名指向的是那个注解,在使用的时候如果不指定annotation的类型的话,默认使用元注解的类型就是Annotation
Class<? extends Annotation> annotation() default Annotation.class;
}
作用:@AliaFor是一个用于声明注解属性别名的注解,它可以让同一个注解里的两个属性成为一个属性,两者互为别名,也可以覆盖元注解的属性
功能:
1.把多个元注解的属性组合在一起形成新的注解
比如:在springboot启动类注解中,他就继承了EnableAutoConfiguration注解的exclude、excludeName属性,和ComponentScan的scanBasePackages、basePackageClasses属性
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM,
classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
}
2.继承注解的功能
比如:如@Controller,@Service,@Repository都继承了@Component的功能,他们的基本作用和@Component完全一样都是标明某个类是Spring的Bean,需要Spring容器进行管理。
不同之处在于对Spring bean进行了归类,从而能对不同类型的Bean进行不同的处理。
@Service代码如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
@AliasFor(annotation = Component.class)
String value() default "";
}
3.在同一个注解中为同一个功能定义两个名称不一样的属性,那么这两个属性彼此互为别名
比如:@RequestMapping注解中的value和path它们两互为别名。
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
String name() default "";
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
String[] consumes() default {};
String[] produces() default {};
}
根据@AliasFor的使用形式我们可以将它分为三类:
1.注解内部的显性别名
public @interface ContextConfiguration {
@AliasFor("locations")
String[] value() default {};
@AliasFor("value")
String[] locations() default {};
}
2.用于元注解属性的显性别名
@ContextConfiguration
public @interface MyTestConfig {
//如案例所示,xmlFiles()指向元注解ContextConfiguration的locations属性,相当于给元注解的locations属性在当前注解中做了一个映射,
//使用@MyTestConfig(xmlFiles='123')和使用@ContextConfiguration(locations='123')效果一样
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] xmlFiles();
}
3.注解中的隐性别名(包括注解中的可传递隐性别名)
@ContextConfiguration
public @interface MyTestConfig {
//如案例所示,value()、groovyScripts()、xmlFiles()都是指向元注解ContextConfiguration的locations属性,所以他们的作用一样互为隐形别名
@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 {};
}
public @interface GroovyOrXmlTestConfig {
//如案例所示,groovy()、xml()分别指向元注解MyTestConfig的groovyScripts属性和元注解ContextConfiguration的locations属性
//因为元注解MyTestConfig的groovyScripts属性指向元注解ContextConfiguration的locations属性,所以groovy和xml互为可传递隐性别名
@AliasFor(annotation = MyTestConfig.class, attribute = "groovyScripts")
String[] groovy() default {};
@AliasFor(annotation = ContextConfiguration.class, attribute = "locations")
String[] xml() default {};
}