@AliasFor注解

顾名思义,@AliasFor表示别名,它可以添加到自定义注解的两个属性上,表示这两个属性互为别名。也就是说,这两个属性其实是同一个含义。

通常所有注解都会有一个属性value,在使用注解时,如果给value进行赋值,默认可以将value省略,如:@RequestMapping(value="name") 就可以写成 @RequestMapping("name") 。

自定义注解

若自定义注解已有一个属性,但是我们想要定义一个能够描述业务的属性,就可以使用@AliasFor与之前已有的属性互为别名。如下代码,name和value就互为别名。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
	@AliasFor("value")
	String name() default "";

	@AliasFor("name")
	String value() default "";
}

若自定义注解继承了另一个注解,要想使用继承过来的属性值,就必须在自定义注解中重新定义一个属性,同时声明该属性是继承过来注解的某个属性的别名。例如:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface MyComponent {
	@AliasFor(annotation = Component.class, attribute = "value")
	String name() default "";
}

自定义注解@MyComponent继承了注解@Component(继承了哪个注解,就需要在自定义注解上引入该注解),name属性与@Component中的value属性互为别名。

拓展

因为我们的自定义注解继承了@Component注解,按理说@MyComponent的作用应该和@Component作用一样,但是此处有一点特殊。如果我们的自定义注解中没有采用value这个属性,而是定义为其它名称,例如name。spring在初始化扫描bean时并不会像使用@Component注解一样,读取注解中自定义的beanName。示例如下,spring加载UserServiceImpl后生成的beanName并不是“userService”,而是“userServiceImpl”。

// 将userServiceImpl重新命名为userService
@MyComponent(name = "userService")
public class UserServiceImpl {
    public void getName(){
        System.out.println("userServiceImpl");
    }
}
@ComponentScan("com.lr.interfaces.aliasFor")
public class AppConfig {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        // 无法获取beanName为userService的实例,只能通过userServiceImpl获取
        UserServiceImpl userService = (UserServiceImpl) context.getBean("userService");
        userService.getName();
    }
}

查看spring源码,发现spring在生成bean对应的beanName时,会先从注解@Component里获取value对应的名称(@Controller等注解本质上也是@Component,具体解释可以参考本文)。所以在自定义注解中如果将value替换为其它属性name,就无法采用自定义的beanName,只能生成默认的别名也就是类名。因此,在自定义注解时,最好采用默认的value。

建议自定义注解将name()修改为value():

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface MyComponent {
    @AliasFor(annotation = Component.class, attribute = "value")
    String value() default "";
}

spring中源码判断核心逻辑

org.springframework.context.annotation.AnnotationBeanNameGenerator#isStereotypeWithNameValue

protected boolean isStereotypeWithNameValue(String annotationType,
                                            Set<String> metaAnnotationTypes, @Nullable Map<String, Object> attributes) {

    // 判断注解中是否包含@Component
    boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) ||
            metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME) ||
            annotationType.equals("javax.annotation.ManagedBean") ||
            annotationType.equals("javax.inject.Named");
    // 判断注解中是否包含属性value
    return (isStereotype && attributes != null && attributes.containsKey("value"));
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大局观的小老虎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值