Annotations——@AliasFor注解和@Inherite注解

8 篇文章 1 订阅

@AliasFor注解的作用

@AliasFor是一个Spring提供的注解,顾名思义,alias单词是别名的意思,可以看出这个注解是起别名用的。具体的例子,我们在其使用方式中一一列举。

几种@AliasFor的使用场景

注解中的属性互相别名

我们摘一段RequestMapping注解中的代码来举例此种情况的使用,为了节省篇幅,省掉了与本例无关的代码。

public @interface RequestMapping {
	@AliasFor("path")
	String[] value() default {};
	@AliasFor("value")
	String[] path() default {};
}

我们用AnnotationUtils来获取RequestMapping注解里具体字段的值

@RequestMapping()
	public void index(){
		Class clazz = DemoApplication.class;
		try {
			clazz.getMethod("index");
			RequestMapping res = AnnotationUtils.findAnnotation(
					DemoApplication.class.getMethod("index"), RequestMapping.class);
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
    }

如果@RequestMapping()不包含任何属性值直接使用,我们会看到path和value属性默认都是一个空数组,这时对任何url的访问都会映射到这个requestMap注解的方法上。
在这里插入图片描述
如果@RequestMapping(path="/index")我们指定path属性的值,会发现value属性的值和path是相同的。
在这里插入图片描述
如果@RequestMapping(path="/index",value=“value”)我们指定同时指定path和value并且指定不同的值,项目启动时就会报错。我们在堆栈信息的最后找到了详细的错误原因:
Caused by: org.springframework.core.annotation.AnnotationConfigurationException: In annotation [org.springframework.web.bind.annotation.RequestMapping] declared on public java.lang.String com.example.demo.DemoApplication.index() and synthesized from [@org.springframework.web.bind.annotation.RequestMapping(path=[/index], headers=[], method=[], name=, produces=[], params=[], value=[index], consumes=[])], attribute ‘path’ and its alias ‘value’ are present with values of [{/index}] and [{value}], but only one is permitted.
由此我们总结出,@Alias注解是指定互为别名的两个属性,可以起到同时赋值的作用。但有一点需要注意的是,如果互为别名的两个属性类型不同,或是默认值default不同,再或是分别设置了不同的值,都会导致项目启动失败。
另外一点是,通过path和value是数组类型我们也可以一个requestMapping注解是可以映射多个路径的,只需要以数组的形式穿进去就好。

对元注解的值进行重写

我们举个例子,例如我们有一个AnnotaionBase注解和一个AnnotationChild注解,AnnotaionBase是AnnotationChild的元注解,如果我想在使用AnnotationChild的同时,覆盖元注解AnnotaionBase中,某个相同类型的属性,代码见下:

@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotaionBase {
    String value() default "base";
}

@Retention(RetentionPolicy.RUNTIME)
@AnnotaionBase
@Inherited
public @interface AnnotationChild {
	@AliasFor(annotation = AnnotaionBase.class, attribute = "value")
    String extendValue() default "child";
}
@AnnotationChild(extendValue = "extendValue")
public class AliasForDemo {
    public static void main(String[] args) {
        AnnotaionBase base = AnnotationUtils.findAnnotation(AliasForDemo.class, AnnotaionBase.class);
        AnnotationChild child = AnnotationUtils.findAnnotation(AliasForDemo.class, AnnotationChild.class);
        AnnotaionBase base2 = AnnotatedElementUtils.findMergedAnnotation(AliasForDemo.class, AnnotaionBase.class);
    }
}

运行结果如下,我们可以看出我们通过给AnnotationChild注解的extendValue属性赋值,并且传递到了元注解AnnotaionBase的value属性上。这种用法有一点需要注意,就是@AliasFor的annotation属性指定的注解,一定要是元注解才行,否则就会报错。
在这里插入图片描述
这里踩了一个坑,因为看别人的博客大部分都说AliasFor注解的这种使用方式,能起到一个类似"子类覆盖父类"的效果,但实际用AnnotationUtils.findAnnotation获取AnnotaionBase注解时,拿到的确实其自身定义的default值。查了很久才发现应该用AnnotatedElementUtils这个工具类,两者具体的区别可以参考这篇博客:https://www.cnblogs.com/hujunzheng/p/9790588.html
了解过@AliasFor注解的第二个用法后,我们就可以看一下@SpringBootApplication这个注解的源码了,这下我们知道为什么通过设置@SpringBootApplication注解中的exclude可以排除特定类的注入,通过设置basePackages可以扫描特定的包向Spring中注入bean。

	@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 {};

@Inherite注解的作用

Inherite意味遗传的、通过继承得到的,从其名字我们知道这个注解跟继承有关。注意,@Inherite注解存在于java.lang.annotation包中,因此这是一个jdk提供的注解。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

我们通过@Target元注解的属性值可以看出,这个@Inherited 是专门修饰注解的,其作用为:注释一个其他注解A,被注解A修饰的超类,其子类也能获得这个注解A。这里所说的仅仅是类之间的继承关系,接口的继承、接口的实现都不会得到父级的注解。
下面我们分别定义两个注解@AnnotationWithInherite和@AnnotationWithoutInherite来测试@Inherite的用法:

@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithInherite {
    String with() default "with";
}
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationWithoutInherite {
    String without() default "without";
}

@Inherite注解对接口是无效的

@AnnotationWithInherite
@AnnotationWithoutInherite
public interface BaseInterface {
}
public interface ChildInterface extends BaseInterface {
}
public void test {
	Annotation[] annotations = ChildInterface.class.getAnnotations();
}

运行结果annotations是一个空数组,证明@Inherite注解对接口是无效的。

@Inherite注解对接口的实现类是无效的

@AnnotationWithInherite
@AnnotationWithoutInherite
public interface BaseInterface {
}
public class implClass implements BaseInterface {
}
public void test {
	Annotation[] annotations = implClass.class.getAnnotations();
}

运行结果annotations是一个空数组,证明@Inherite注解对接口的实现类是无效的。

@Inherite注解对类继承是有效的

@AnnotationWithInherite
@AnnotationWithoutInherite
class BaseClass {
}
class ChildClass extends BaseClass{
}
public void test {
	Annotation[] annotations = ChildClass.class.getAnnotations();
}

运行结果annotations中有@AnnotationWithInherite这个注解,说明被@Inherite作用的注解,是能通过类继承关系由父类传递到子类的。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
@RequestBody 注解是 Spring Framework 中的一个注解,它用于将 HTTP 请求的请求体部分绑定到方法的参数上。在 Spring MVC 或 Spring Boot 应用程序中,通常用于处理 POST、PUT、PATCH 等请求方法中的 JSON 或表单数据。 以下是 @RequestBody 注解的源码: ```java package org.springframework.web.bind.annotation; import org.springframework.core.annotation.AliasFor; import org.springframework.http.MediaType; import java.lang.annotation.*; @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestBody { @AliasFor("contentType") String value() default ""; @AliasFor("value") String contentType() default ""; boolean required() default true; Class<? extends HttpMessageConverter<?>>[] converters() default {}; Class<? extends Annotation>[] annotations() default {}; } ``` 这段源码定义了 @RequestBody 注解的属性和行为: - `value` 和 `contentType` 属性用于指定请求体的媒体类型。默认为空字符串,表示自动检测请求的媒体类型。 - `required` 属性用于指定请求体是否为必需,默认为 true。 - `converters` 属性用于指定用于将请求体转换为方法参数的对象的 HttpMessageConverter 实现类。默认为空数组,表示使用 Spring 的默认转换器。 - `annotations` 属性用于指定其他注解,以进一步自定义请求体的处理方式。 通过使用 @RequestBody 注解,我们可以将请求体的内容以 JSON 或表单数据的形式绑定到方法参数上,方便地进行数据的处理和转换。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值