java—如何在构建期间或在SpringBoot启动期间验证注解?

5w9g7ksd  于 2021-07-23  发布在  Java
关注(0)|答案(3)|浏览(295)

比如说,我有一个 @TimedMillis 和一个 @TimedSeconds 注解。它们所做的是记录方法执行持续时间,一个以毫秒为单位,另一个以秒为单位。
把它们放在同一个方法上是没有任何意义的。一个方法可以有这些注解中的一个,也可以没有,但不能同时有两个。
如何检查一个方法在构建过程中不同时具有这两个属性(最好)?如果在构建期间不可能,如何在启动期间执行此操作并阻止应用程序启动?我见过hibernate在启动时这样做。虽然它没有阻止应用程序启动,但它确实阻止了应用程序工作。

kiayqfof

kiayqfof1#

您可以使用reflections库轻松地扫描包及其所有子包,以查找包含用特定注解注解的方法的类。
然后,您可以在任何合适的地方注入验证逻辑。
例如,您可以:
添加反射依赖项:

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.12</version>
</dependency>

添加验证逻辑,如果需要,甚至比spring bootstrap更早,比如:

public static void main(String[] args) {
    validateAnnotations();
    SpringApplication.run(ExampleApplication.class, args);
  }

  private static void validateAnnotations() {
    Set<Method> annotatedMethods = 
      new Reflections("com.example", new MethodAnnotationsScanner())
      .getMethodsAnnotatedWith(TimedMillis.class);

    annotatedMethods.stream()
    .filter(method -> method.getDeclaredAnnotationsByType(TimedSeconds.class).length > 0)
    .findFirst()
    .ifPresent(method -> {
      throw new IllegalStateException("Invalid annotations for method " + method);
    });
  }
zz2j4svz

zz2j4svz2#

还有另一种选择——通过注解本身使之不可能。
这种方法假设@timedmillis和@timedseconds实际上非常相似,并且可以重构为单个注解。
为了实现这样的功能,可以引入新的注解,它将提供所需的时间单位作为值。

@Target({ElementType.METHOD})
public @interface Timed {

    /**
     * Defines time unit of duration.
     *
     * @return duration time unit
     */
    TimeUnit timeUnit();
}

它将有助于实现所需的功能,因为不允许重复的注解(仅当不使用@repeatable标记时)

twh00eeo

twh00eeo3#

您可以定义一个自定义注解处理器来执行此验证。注解处理将在生成时进行。下面是一个关于如何使用注解处理api的不错的教程:https://www.baeldung.com/java-annotation-processing-builder

相关问题