在 Lombok 中,语法 `@__()` 是什么意思?

30

我已经使用 Lombok 工具工作并积极使用了两个月。对于 Java ,我略微熟悉一些。但是,这是我第一次面对这种语言中的以下语法结构:

@RequiredArgsController(onController = @__(@Autowired))
                                       ^^^

那是什么意思,它是如何被编译的?


1
一些挖掘发现了这个网址:https://projectlombok.org/features/experimental/onX.html:*`@__`类型是对注解类型`__`(双下划线)的注释引用,但实际上并不存在*。虽然我对Lombok一无所知。 (还有这封邮件 - Tunaki
3个回答

31
这是一种实验性的Lombok语法,旨在支持引用多个注释时的间接层,而不是使用Class<?>[]。 引入了一个有点奇怪的语法:要使用3个onX功能中的任何一个,必须将要应用于构造函数/方法/参数的注释包装在@__(@AnnotationGoesHere)中。要应用多个注释,请使用@__({@Annotation1, @Annotation2})。这些注释本身也可以有参数。

https://projectlombok.org/features/experimental/onX.html

来自Lombok开发人员Roel Spilker的解释:

这样做的原因是javac在解析阶段已经解析注解,并且如果它确定注解无效,则会给出错误。通过使用不存在的注解@__,它无法确定它是否是伪造的(可能是由注解处理器创建的),并且不会立即给出错误。这给了Lombok时间来完成它的工作并从代码中删除@__


11
原因在于 javac 在解析阶段已经解析了注解,并且如果它能够确定注解无效,就会报错。通过使用不存在的注解 @__,它不能确定它是否是伪造的(可能是由注解处理器创建的),并且不会立即报错。这给了 Lombok 时间来完成其工作并从代码中删除 @__ - Roel Spilker
@RoelSpilker 这是否意味着它本来可以是其他任何东西?比如 @placeholder_annotation 或者 @temp_annotation 或者 @ignore_this_it_is_ephemeral - asgs

12

这意味着生成的构造函数(而不是控制器)也将添加@Autowired注解,以便Spring可以发挥其魔力。使用lombok,您可以像这样编写代码

@RequiredArgsConstructor(onConstructor=@__(@Autowired(required=true)))
public class FooController {
    private final FooService service;
    interface FooService {}
}

而lombok将在编译期间将其转换

public class FooController {
    private final FooService service;
    @Autowired(required=true)
    public FooController(FooService service) {
        this.service = service;
    }
}

@__ 被用来克服注解类型限制,因为

@interface MultipleAnnotations {
    Annotation[] value();
}

不起作用,因为所有注释的超类型本身并不是注释。

@interface MultipleAnnotations {
    Class<? extends Annotation>[] value();
}

不允许在注解中使用参数:@MultipleAnnotations(SomeAnnotation.class)


可以直接使用 Class[],并在编译时检查 isAnnotation() - OrangeDog
1
@OrangeDog 不允许在注释中使用参数。 - zapl
3
Lombok团队曾经提交过一个提案,希望为注解添加Annotation[]的可能性,但被拒绝了。也许有一天我们可以重新启动这个提案... - Roel Spilker

7
对于JDK8用户来说,如果对这种奇怪的语法感到困惑,还有一种更简洁的方法,如此处所述 - 在javac8及更高版本中,您可以在onMethod、onParam或onConstructor后面添加一个下划线。 因此,它将从@RequiredArgsController(onController = @__(@Autowired))变为@RequiredArgsController(onController_ = @Autowired)

3
我认为这是一个 @RequiredArgsConstructor(onConstructor_ = @Autowired) 而不是 @RequiredArgsController。 - Krishna
这就是为什么明确的方法比Lombok(或类似的)隐式声明更可取的地方。明确的情况使得在代码中查找引用和快速扫描数据/依赖流程对人类来说更容易。简洁是好的,但过于简洁则会走向极端。记住,其他人也需要能够阅读你的代码。 - Charlie Reitzel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,