是否可以在 java 中创建注释包(即应用其他注释的注释)?

Is it possible to create an annotation bundle in java (i.e. an annotation that applies other annotations)?

假设以下代码在代码库中经常出现:

// old wet code
@AnnotationA
@AnnotationB
@AnnotationC
class SomeClass {
   // ...
}

是否可以创建应用其他注释(A、B、C)并生成相同功能的注释 AnnotationBundle?这只会用于 DRY 代码库,不会意外忘记 class.

上的单个注释
// new DRY code
@AnnotationBundle
class SomeClass {
   // ...
}

看起来这在 Java 中通过 伪造 meta-annotations(例如 Spring MVC - Meta Annotations, What Are Meta-Annotations in Java?))在技术上是可行的。

但这并非对所有注释都是如此 - 例如,lombok 还不允许这样做并将注释限制为 class 类型(而不是 @interface)。

简答

不,你不能。 Java 本身没有元注释的概念。

备选方案 1:Spring 注释

有人提到 Spring 元注释。是的,在 Spring 中你可以这样做,但这只是因为 Spring 实现了一些非常令人印象深刻的内部机制,涉及反射和其他机制以实现这个概念。所以

  • 要么您使用 Spring 并依赖其功能,
  • 或者您重建类似的东西并确保您自己的应用程序使用您正在构建的框架
  • 或者您提取 Spring 注释内容并在 Spring 之外使用它。

前段时间我做了后者作为手指练习,因为我想看看是否有可能提取它。因为和其他Spring纠缠的很深,所以挺难的,不过最后我还是做到了。

结果是 here,Spring 注释实用程序的 stand-alone 版本可在 Spring 之外使用。 如果您阅读自述文件,您可以了解我是如何做到的,因为我将其记录为将来类似提取的模板。实际上,我从未使用过自己的 stand-alone Spring 注释实用程序,但我邀请您这样做。 Spring 可以用注释做更多的事情,例如检查 class 实现的接口上是否有注解,超级 class 方法上的注解等。这非常强大,解释了为什么 Spring 可以实现一些 annotation-based 的东西开箱即用的 JRE 是不可能的。例如。 JDK 没有继承注解的概念,除了(可选)从 superclass 到 subclass,但不是从接口到 class,也不是从方法到覆盖方法。

您可以克隆并构建我的 GitHub 存储库,看看它是否可以帮助您完成您想做的事情。但它不会自己神奇地发生,你必须调用相应的方法才能收集这样的信息。

备选方案 2:AspectJ

作为替代方案,您可以使用 AspectJ(我说的是真正的 AspectJ,而不是 Spring AOP)并使用 ITD(inter-type 定义),例如使 class 实现接口或在类型上声明注释。这样您就可以实现模拟元注释的方面。方面会处理所有事情,应用程序不需要知道它。不过,我不确定你是否想学习 AOP 来做到这一点。