类型注解与重复注解一些限制

类型注解

原来注解只能用于声明,从JDK 8开始,注解还可以用于大多数使用类型的地方,这种注解称为类型注解。类型注解允许工具对代码执行额外的检查,从而帮助避免错误。javac本身一般不执行这些检查,这种工具需要作为编译器插件发挥作用。

例子
@Target(ElementType.TYPE_USE)
public @interface TypeAnno {
}

@Target(ElementType.TYPE_USE) public @interface MaxLen { int value(); } @Target(ElementType.TYPE_USE) public @interface Unique { } @Target(ElementType.TYPE_PARAMETER) public @interface What { String description(); } @Target(ElementType.FIELD) public @interface NotNull { } @Target(ElementType.METHOD) public @interface Recommended { } // 注解类型参数 public class TypeTest<@What(description = "Generic data type") T> { // 注解字段类型 private @TypeAnno String first; // 注解字段声明 private @NotNull String second; // 注解数组元素类型 private @TypeAnno Integer[] nums; // 注解数组级别 private String @MaxLen(5) [] @MaxLen(10) [] data; // 注解构造函数 public @Unique TypeTest() { } // 注解this的类型 public int f1(@TypeAnno TypeTest<T> this, int x) { return 10; } // 注解方法返回类型 public @TypeAnno Integer f2(int j, int k) { return j + k; } // 注解方法声明 public @Recommended Integer f3(String str) { return str.length() / 2; } // 注解异常类型 public void f4() throws @TypeAnno NullPointerException { // ... } public static void test() { TypeTest<@TypeAnno Integer> obj1 = new TypeTest<>(); // 注解实际类型参数 @TypeAnno TypeTest<Integer> obj2 = new @TypeAnno TypeTest<>(); // 注解实例类型 Object x = new Integer(10); Integer y; y = (@TypeAnno Integer) x; // 注解强制类型转换 } } // 注解被继承的类型 public class SubTypeTest extends @TypeAnno TypeTest<Integer> { // ... } 
注意
  • 类型注解必须包含ElementType.TYPE_USE作为目标。
  • 类型注解需要放到应用该注解的类型前面。
  • 不能对void返回类型添加注解。
  • @Target可以用于消除声明注解和类型注解的模糊性问题,比如上面例子中@TypeAnno注解字段类型而@NotNull注解字段声明;@TypeAnno注解方法返回类型而@Recommended注解方法声明。
this对象

this是所有实例方法的隐式参数,它的类型必须是其类的类型。类型注解可以注解this的类型,但是需要使用JDK 8的一个新特性,从JDK 8开始可以显式地将this声明为方法的第一个参数。

除非是要注解this的类型,否则没必要声明this。并且显示声明this没有改变方法签名,因为默认也会隐式声明this。


重复注解

JDK 8新增了另一种注解特性,这种特性称为重复注解,它允许在相同元素上重复应用同一个注解。

@Repeatable注解

可重复的注解必须用@Repeatable进行注解。@Repeatable定义在java.lang.annotation中,它的value域指定了重复注解的容器类型。源码如下所示:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable { /** * Indicates the <em>containing annotation type</em> for the * repeatable annotation type. * @return the containing annotation type */ Class<? extends Annotation> value(); } 
容器注解

重复注解的容器类型被指定为注解。容器注解的value域是重复注解类型的数组。要创建重复注解,必须创建容器注解,然后将该容器注解的类型作为@Repeatable注解的参数。

@Retention(RetentionPolicy.RUNTIME)
@Repeatable(RepeatedAnnos.class)
public @interface RepeatableAnno { String name() default "test"; int value() default 100; } @Retention(RetentionPolicy.RUNTIME) public @interface RepeatedAnnos { RepeatableAnno[] value(); } 
获取重复注解的方式
  • 使用getAnnotation()方法获取重复注解,要使用容器注解作为参数,而不是重复注解。
public class RepeatableTest { @RepeatableAnno(name = "first annotation", value = 10) @RepeatableAnno(name = "second annotation", value = 20) public static void test() { RepeatableTest obj = new RepeatableTest(); try { Class<?> c = obj.getClass(); Method m = c.getMethod("test"); Annotation anno = m.getAnnotation(RepeatedAnnos.class); System.out.println(anno); } catch (NoSuchMethodException e) { System.out.println("Method Not Found."); } } public static void main(String[] args) throws Exception { test(); } } 

上面例子的输出如下:
@RepeatedAnnos(value=[@RepeatableAnno(name=first annotation, value=10), @RepeatableAnno(name=second annotation, value=20)])

  • 获取重复注解的另一种方式是使用JDK 8添加到AnnotatedElement中的新方法,它们能够直接操作重复注解。这些方法包括getAnnotationsByType()和getDeclaredAnnotationsByType()。
Annotation[] annos = m.getAnnotationsByType(RepeatableAnno.class);
for (Annotation anno : annos) {
    System.out.println(anno);
}

一些限制

使用注解声明有一些限制:

  • 一个注解不能继承另一个注解。
  • 注解声明的成员方法不能带参数。
  • 注解声明的成员方法不能指定throws子句。
  • 注解不能被泛型化。



 

 

Java8对注解处理提供了两点改进:可重复的注解及可用于类型的注解

1.可重复注解

Java8以前定义注解:

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation { String value() default "mobei"; } 

使用:


 
image.png

可以看到这时当做重复注解使用就报错了。
如果要使用重复注解,必须先定义一个容器:

//注解容器
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotations { MyAnnotation[] value(); } 

在重复注解上标注@Repeatable注解并指定容器类:

//使用可重复注解:①必须使用@Repeatable注解标注该注解②在@Repeatable注解中指定该注解的注解容器
@Repeatable(MyAnnotations.class)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, TYPE_PARAMETER})//TYPE_PARAMETER:J8中新增加的类型注解 @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String value() default "mobei"; } 

使用:


 
image.png

不报错,测试:

    @Test
    public void test1() throws Exception { Class<TestAnnotation> clazz = TestAnnotation.class; Method m1 = clazz.getMethod("show"); MyAnnotation[] mas = m1.getDeclaredAnnotationsByType(MyAnnotation.class); for (MyAnnotation myAnnotation : mas) { System.out.println(myAnnotation.value()); } } 

输出:

Hello
World
2.类型注解

在上面的MyAnnotation的@Target注解中加入TYPE_PARAMETER

//使用可重复注解:①必须使用@Repeatable注解标注该注解②在@Repeatable注解中指定该注解的注解容器
@Repeatable(MyAnnotations.class)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, TYPE_PARAMETER})//TYPE_PARAMETER:J8中新增加的类型注解 @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String value() default "mobei"; } 

可以修饰参数:

@MyAnnotation("Hello")
@MyAnnotation("World") public void show(@MyAnnotation("abc") String str){ } 

 

转载于:https://www.cnblogs.com/exmyth/p/11408644.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
自定义注解AOP防重复提交是一种通过在代码中添加自定义注解的方式来实现防止重复提交的功能。这种方法可以有效地避免代码耦合性过强,提高代码的可读性和可维护性。 具体实现的方案可以有多种,以下是几种常见的方案: 1. Token验证:在每次请求中添加一个唯一的Token标识,服务端接收到请求后将Token保存在缓存中,然后进行重复提交的验证。如果同一个Token已经存在于缓存中,则表示该请求已经被处理过,可以拒绝重复提交。 2. 请求参数验证:通过对请求参数进行校验,判断是否已经存在相同的请求参数,如果存在则表示重复提交。可以使用缓存或者数据库来存储已经处理过的请求参数,通过查询来进行重复提交的验证。 3. 时间窗口验证:通过设置一个时间窗口,限制在该时间窗口内只接受一次请求。可以使用缓存或者数据库记录请求的时间戳,每次接收到请求时与最近一次的时间戳进行比对,如果在时间窗口内已经存在过请求,则拒绝重复提交。 以上方案都可以使用Redis作为缓存来进行存储和验证操作。可以通过引入相关的依赖来使用Spring Boot集成的Redis组件和Jedis依赖。 通过使用自定义注解AOP来实现防重复提交可以有效地提高代码的可读性和可维护性,同时也能够减轻服务器的负载,避免因为重复提交而导致的服务器宕机等问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值