在Java中是否可以创建一个注解包(即应用其他注解的注解)?

huangapple go评论96阅读模式
英文:

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

问题

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

// 旧的重复代码
@AnnotationA
@AnnotationB
@AnnotationC
class SomeClass {
   // ...
}

是否可以创建一个名为 AnnotationBundle 的注解,它应用其他注解(A、B、C),并生成相同的功能?这仅用于使代码库更加干净,并防止在类上意外遗漏单个注解。

// 新的精简代码
@AnnotationBundle
class SomeClass {
   // ...
}
英文:

Assume the following code is seen frequently in a codebase:

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

Is it possible to create an annotation AnnotationBundle that applies the other annotations (A, B, C) and generates the same functionality? This would only be used to DRY the codebase and not accidentally forget a single annotation on a class.

// new DRY code
@AnnotationBundle
class SomeClass {
   // ...
}

答案1

得分: 1

短答案:不可以。Java中没有“元注解”的概念。

备选方案1:Spring注解
有人提到了Spring元注解。是的,在Spring中可以做到这一点,但只是因为Spring实现了一些相当令人印象深刻的内部机制,涉及反射和其他机制,以实现这个概念。所以,
要么您使用Spring并依赖于其功能,
要么您重新构建类似的东西,并确保您自己的应用程序使用您正在构建的框架,
要么您提取Spring注解的内容并在Spring之外使用它。
我曾经因为想看看是否有可能提取它而进行了后者,这是一个手指练习。因为它与其他Spring内容深度纠缠在一起,所以这相当困难,但最终我成功了。
结果是这里,这是一个独立的Spring注解工具的版本,可以在Spring之外使用。如果您阅读自述文件,您可以了解我是如何做到的,因为我把它记录下来,作为以后类似提取的模板。实际上,我从来没有使用过我自己的独立Spring注解工具,但我邀请您这样做。Spring还可以使用注解执行更多操作,例如检查类实现的接口上是否有注解,超类方法上的注解等。这非常强大,解释了为什么Spring可以实现一些基于注解的操作,而这些操作在JRE中是无法做到的。例如,JDK没有继承注解的概念,除了(可选地)从超类到子类,而不是从接口到类,也不是从方法到覆盖方法。
您只需克隆和构建我的GitHub存储库,看看它是否能帮助您完成想要做的事情。但这不会自动发生,您必须调用相应的方法来收集这样的信息。

备选方案2:AspectJ
作为另一种选择,您可以使用AspectJ(我正在谈论真正的AspectJ,而不是Spring AOP),并使用ITD(inter-type definitions)来使类实现接口或在类型上声明注解,以模拟元注解。切面会负责一切,应用程序不需要知道它。不过,我不确定您是否想要学习AOP来做这件事。

英文:

Short answer

No, you cannot. There is no concept of meta annotations in Java as such.

Alternative 1: Spring annotations

Someone mentioned Spring meta annotations. Yes, in Spring you can do this, but only because Spring implements some quite impressive internal machinery involving reflection and other mechanisms in order to implement the concept. So

  • either you use Spring and rely on its capabilities,
  • or you rebuild something similar and make sure that your own applications use the framework you are building
  • or you extract the Spring annotation stuff and use it outside of Spring.

I did the latter a while ago as a finger exercise because I wanted to see if it is even possible to extract it. It was quite difficult because it is entangled quite deeply with other Spring stuff, but in the end I managed to do it.

The result is here, a stand-alone version of Spring annotation utilities usable outside of Spring. If you read the readme, you can learn how I did it because I documented it as a template for similar extractions in the future. I actually never used my own stand-alone Spring annotation utilities, but I am inviting you to do so. There are many more things Spring can do with annotations, e.g. check if there are annotations on interfaces implemented by a class, annotations on super class methods etc. This is quite powerful and explains why Spring can implement some annotation-based stuff which are impossible with the JRE out of the box. E.g. the JDK has no concept of inheriting annotations except (optionally) from superclass to subclass, but not from interface to class and not from method to overriding method.

You can just clone and build my GitHub repository and see if it helps you do the things you want to do. But it won't magically happen by itself, you have to call the corresponding methods in order to gather information like that.

Alternative 2: AspectJ

As an alternative, you can use AspectJ (I am talking about real AspectJ, not Spring AOP) and use ITD (inter-type definitions) in order to e.g. make a class implement an interface or declare annotations on a type. This way you could implement an aspect emulating meta annotations. The aspect would take care of everything, the application would not need to know about it. I am not sure if you want to learn AOP in order to do this, though.

答案2

得分: 0

看起来在Java中在技术上是可能的,通过“伪造”元注解(例如Spring MVC - 元注解Java中的元注解是什么?)。

但并非所有注解都适用于这种情况 - 例如,lombok目前不允许这样做,并将注解限制为类类型(而不是@interface)。

英文:

It looks like this is technically possible in Java by faking meta-annotations (e.g. Spring MVC - Meta Annotations, What Are Meta-Annotations in Java?)).

But this is not true for all annotations - for example, lombok does not allow this yet and restricts annotations to class types (rather than @interface).

huangapple
  • 本文由 发表于 2020年9月16日 20:08:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/63919783.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定