使用龙目岛项目安全吗?

如果你不知道的话,Project Lombok可以帮助解决一些Java的烦恼,比如生成带有注释的getter和setter甚至简单的JavaBean生成@Data。它真的可以帮助我,特别是在50个不同的事件对象中,你有多达7个不同的字段需要用getter来构造和隐藏。我可以用这个删除几乎一千行代码。

然而,我担心从长远来看,这将是一个后悔的决定。当我提到它时,火焰战争将在##Java Freenode通道中爆发,提供代码片段将混淆可能的helper, 人们会抱怨缺少JavaDoc,并且未来的提交者可能无论如何都会删除它。我很享受积极的一面,但我担心消极的一面。

那么:在任何项目中使用Lombok安全吗?积极的影响抵得上消极的影响吗?

152814 次浏览

听起来好像您已经认为Project Lombok为您提议的新项目提供了显著的技术优势。(首先要澄清的是,我对龙目岛项目没有特别的看法,无论如何。)

在某些项目(开源或其他方式)中使用Project Lombok(或任何其他改变游戏规则的技术)之前,您需要确保项目涉众同意这一点。这包括开发人员和任何重要的用户(例如,正式或非正式的赞助商)。

你提到了这些潜在的问题:

当我提到它时,火焰战争将在##Java Freenode频道爆发,

一件容易的事。忽略/不要参与战火,或者只是避免提及龙目岛。

提供代码片段会让可能的助手感到困惑,

如果项目策略是使用Lombok,那么可能的助手将需要习惯它。

人们会抱怨缺少JavaDoc,

这是他们的问题。心智正常的人都不会把自己组织的源代码/文档规则死板地应用到第三方开源软件上。项目团队应该可以自由地设置与所使用的技术相适应的项目源代码/文档标准。

(跟踪 - Lombok开发人员认识到不能为合成的getter和setter方法生成javadoc注释是一个问题。如果这是您的项目的主要问题,那么另一种选择是创建并提交Lombok补丁来解决这个问题。)

未来的提交者可能会把它全部删除。

那没开!如果商定的项目策略是使用Lombok,那么毫无理由地去Lombok代码的提交者应该受到惩罚,如果有必要,他们的提交权将被撤销。

当然,这是假设你已经得到了涉众的支持……包括开发者。它还假定你已经准备好为自己的理由辩护,并适当地处理不可避免的不同声音。

继续使用Lombok,你可以在必要时“delombok”你的代码之后http://projectlombok.org/features/delombok.html

就我个人而言(因此主观上),我发现使用Lombok使我的代码更能表达我试图实现的目标,与IDE/自己实现的复杂方法(如hashcode &平等的。

当使用

@EqualsAndHashCode(callSuper = false, of = { "field1", "field2", "field3" })

保持等号更容易与任何IDE/自己的实现相比,HashCode保持一致并跟踪哪些字段被计算。当您仍然定期添加/删除字段时,这一点尤其正确。

@ToString注释及其参数也是如此,它们清楚地传达了包含/排除字段、getter的使用或字段访问以及是否调用super.toString()的所需行为。

同样,通过用@Getter@Setter(AccessLevel.NONE)注释整个类(并可选择覆盖任何发散的方法),可以立即清楚哪些方法将可用于字段。

好处无穷无尽。

在我看来,这不是关于减少代码,而是关于清楚地传达您想要实现的目标,而不是必须从Javadoc或实现中找到答案。减少的代码只是使它更容易发现任何发散方法实现。

当我向我的团队展示项目时,他们的热情很高,所以我认为你不应该害怕团队的反应。

  • 就ROI而言,集成它很简单,并且不需要对其基本形式进行代码更改。(只需向类中添加一个注释)

  • 最后,如果您改变了主意,您可以运行unlombok,或让IDE创建这些setter、getter和ctor(我认为一旦他们看到您的pojo变得多么清晰,就没有人会要求它们了)

在过去的一年里,我在几乎所有的项目中都使用了Lombok,但不幸的是,我把它移除了。在一开始,这是一种非常干净的开发方式,但为新团队成员设置开发环境并不是非常容易和直接的。头痛时,我就把它去掉了。但这是一个很好的工作,需要一些更简单的设置。

TL;博士:

是的,使用起来很安全,我建议使用它。(2022年5月)


原来的答案

今天刚开始使用龙目岛。到目前为止,我很喜欢它,但我没有看到它的一个缺点是重构支持。

如果你有一个带有@Data注释的类,它会根据字段名为你生成getter和setter。如果您在另一个类中使用这些getter中的一个,然后确定该字段的命名很糟糕,它将不会找到这些getter和setter的用法,并将旧名称替换为新名称。

我认为这必须通过IDE插件来完成,而不是通过Lombok。

< p > 更新(2013年1月22日)
在使用Lombok 3个月之后,我仍然推荐它用于大多数项目。然而,我确实发现了另一个与上面列出的相似的缺点

如果你有一个类,比如MyCompoundObject.java,它有两个成员,都用@Delegate注释,比如myWidgetsmyGadgets,当你从另一个类调用myCompoundObject.getThingies()时,不可能知道它是委托给Widget还是Gadget,因为你不能再在IDE内跳转到源代码。

使用Eclipse“生成委托方法”为您提供相同的功能,同样快速,并提供源跳转。缺点是它用样板代码把你的源代码弄得一团糟,使你的注意力从重要的东西上转移开。

< p > 更新2(2013年2月26日)
5个月后,我们仍在使用Lombok,但我还有其他一些烦恼。缺少声明的getter &当你试图熟悉新代码时,Setter有时会很烦人

例如,如果我看到一个名为getDynamicCols()的方法,但我不知道它是关于什么的,我就需要跨越一些额外的障碍来确定这个方法的目的。其中一些障碍是Lombok,一些是缺乏Lombok智能插件。障碍包括:

  • 缺少JavaDocs。如果我javadoc该字段,我希望getter和setter将通过Lombok编译步骤继承该javadoc。
  • 跳转到方法定义将我跳转到类,而不是生成getter的属性。这是一个插件问题。
  • 显然,除非生成或编码方法,否则无法在getter/setter中设置断点。
  • 注意:这个引用搜索不是一个问题,因为我最初认为它是。不过,您确实需要使用一个透视图来启用Outline视图。对大多数开发人员来说不是问题。我的问题是我正在使用Mylyn,它正在过滤我的Outline视图,所以我没有看到方法。缺乏参考资料搜索。如果我想知道谁在调用getDynamicCols(args...),我必须生成或编码setter,以便能够搜索引用。
< p > 更新3(2013年3月7日)
我想是在学习使用Eclipse中的各种做事方式。实际上,您可以在Lombok生成的方法上设置条件断点(BP)。使用Outline视图,你可以右键单击方法Toggle Method Breakpoint。然后当你点击BP时,你可以使用调试Variables视图来查看生成的方法如何命名参数(通常与字段名相同),最后,使用Breakpoints视图右键单击BP并选择Breakpoint Properties...来添加条件。好。< / p > < p > 更新4(2013年8月16日)
Netbeans不喜欢在Maven pom中更新Lombok依赖项。项目仍然会编译,但是文件会因为有编译错误而被标记,因为它看不到Lombok正在创建的方法。清除Netbeans缓存可以解决这个问题。不确定是否有“清洁计划”;选项,就像Eclipse中那样。小问题,但想让大家知道 < p > 更新5(2014年1月17日)
Lombok并不总是能很好地与Groovy一起工作,或者至少groovy-eclipse-compiler。您可能不得不降低编译器的版本。 Maven Groovy和Java + Lombok < / p > < p > 更新6(2014年6月26日)
警告一句。Lombok有点让人上瘾,如果您从事的项目由于某种原因不能使用它,它会让您感到厌烦。

.

. < p > 更新7(2014年7月23日)
这是一个有点有趣的更新,因为它直接解决了OP询问的采用Lombok的安全

自v1.14起,@Delegate注释已降级为实验性状态。详细信息记录在他们的网站(龙目岛委托文档)上。

问题是,如果你使用这个功能,你的退出选项是有限的。我认为选项如下:

  • 手动删除@Delegate注释并生成/手工编码委托代码。如果在注释中使用属性,这就有点困难了。
  • Delombok包含@Delegate注释的文件,并可能添加回你想要的注释中。
  • 永远不要更新Lombok或维护一个分叉(或使用体验特性)。
  • Delombok您的整个项目,停止使用Lombok。

据我所知,Delombok没有删除注释子集的选项;至少对于单个文件的上下文中是这样的。我打开请求此功能的票据与Delombok旗帜,但我不期望在不久的将来。

< p > 更新8(2014年10月20日)
如果这是您的一个选择,Groovy提供了与Lombok相同的大部分优点,以及大量其他特性,包括@ delegate。如果你认为你很难把这个想法推销给当权者,看看@CompileStatic@TypeChecked注释,看看它是否能帮助你。事实上,Groovy 2.0发行版的主要关注点是静态安全.

. < p > 更新9(2015年9月1日)
龙目岛仍然是积极维护和增强,这预示着采用的安全水平。@Builder注释是我最喜欢的新特性之一 < p > 更新10(11月17日至15日)
这似乎与OP的问题没有直接关系,但值得分享。如果你正在寻找工具来帮助你减少你编写的样板代码的数量,你也可以查看谷歌汽车 -特别是AutoValue。如果你看他们的的幻灯片,列出龙目岛作为一个可能的解决方案,他们正在试图解决的问题。他们为龙目岛列出的缺点是:

  • 插入的代码是不可见的(你不能"see"它生成的方法)[注释-实际上你可以,但它只需要一个反编译器]
  • 编译器hack是不标准的和脆弱的
  • “在我们看来,你的代码不再是真正的java”;

我不确定我在多大程度上同意他们的评价。考虑到幻灯片中记录的AutoValue的缺点,我将坚持使用Lombok(如果Groovy不是一个选项)。

< p > 更新11(2016年2月8日)
我发现Spring Roo有一些类似的注释。我有点惊讶地发现Roo仍然存在,并且查找注释的文档有点粗糙。移除看起来也不像去龙目岛那么容易。龙目岛似乎是更安全的选择 < p > 更新12(2016年2月17日)
当我试图为我目前正在从事的项目提出为什么将龙目岛带入龙目岛是安全的理由时,我发现了一块添加了v1.14 - 配置系统!这意味着您可以配置项目以禁止团队认为不安全或不可取的某些特性。更好的是,它还可以使用不同的设置创建特定于目录的配置。

< p > 更新13(16年10月4日)
如果这类事情对你很重要,奥利弗Gierke觉得将Lombok添加到Spring Data Rest是安全的 < p > 更新14(17年9月26日)
正如@gavenkoa在OPs问题的评论中指出的那样,JDK9编译器支持还不可用 (Issue #985)。这听起来对龙目岛团队来说也不是一个容易解决的问题 < p > 更新15(18年3月26日)
龙目岛更新日志显示为v1.16.20 & 现在可以在JDK1.9上编译lombok了"即使# 985仍然打开

然而,为了适应JDK9而进行的更改需要一些突破性的更改;所有这些都与配置默认值中的更改隔离。有点令人担忧的是,他们引入了突破性的变化,但这个版本只是取消了“增量”。版本号(从v1.16.18到v1.16.20)。由于这篇文章是关于安全的,如果你有一个类似yarn/npm的构建系统,自动升级到最新的增量版本,你可能会猛然醒悟。

更新16(19年1月9日)

据我所知,JDK9问题已经解决和Lombok似乎可以与JDK10,甚至JDK11一起工作。

我注意到的一件事是,从安全角度考虑,从v1.18.2到v1.18.4的更改日志列出了两个BREAKING CHANGE!?我不确定一个突破性的变化是如何在一个永久的“补丁”中发生的。更新。如果您使用自动更新补丁版本的工具,可能会出现问题。

更新17(21年3月17日)

围绕JDK 16, Lombok开发人员和OpenJDK开发人员之间发生了一些戏剧性的变化。JDK开发人员认为, Lombok通过JDK团队想要关闭的漏洞利用了未发布的JDK内部,但由于各种原因故意留下了漏洞。

他们表达了他们的担忧(关于龙目岛的安全)这样:

对内部函数的所有访问都将像以前一样可用,前提是 客户端应用程序显式地允许它,并承认它是 故意承担任何维护(或安全)问题,这可能 需要。< / p > 虽然Lombok可能认为他们在欺骗OpenJDK,但他们所做的一切 是在宣布他们有意欺骗自己的用户。

可能很快就会有一天,Lombok将无法围绕JDK的安全限制找到任何更具创造性的解决方案。即使他们这样做了,在您的项目中使用Lombok的安全性也可能存在问题。

更新18(22年5月11日)

最近的一条评论要求我做个总结,所以我把它放在了最上面。

简单的回答是,它使用起来非常安全,如果我们正在编写Java代码,我强烈建议使用它。

考虑到对JDK 17的支持已经有一段时间了,并且是在JDK正式发布后不到一个月才发布的,因此Lombok的安全性很高。如果需要,你可以随时去龙目岛。

作为一名顾问,我可以看到很多不同的公司是如何编写代码的。在过去的5年里,我的每个客户都使用龙目岛。这些都是财富1000强企业。它加快了开发速度,减少了出错的可能性。

也就是说,您仍然需要跟上JDK的最新特性。考虑使用Java record关键字使对象不可变,而不是使用一些Lombok特性。在有意义的地方使用Lombok。使用Lombok配置选项来防止以您不同意的方式使用它。

所以除非有重大的事情发生,这可能是我最后一次更新这个答案。谢谢你们的投票。我很高兴这有帮助。

我知道我迟到了,但我无法抗拒诱惑:喜欢Lombok的人也应该看看Scala。您在Lombok中发现的许多好想法都是Scala语言的一部分。

关于您的问题:让开发人员尝试Lombok肯定比尝试Scala更容易。试一试,如果他们喜欢,那就试试Scala。

免责声明:我也喜欢Java !

想要使用lombok的@ToString,但很快在Intellij IDEA中重新构建项目时遇到了随机编译错误。在增量编译成功完成之前,必须多次点击编译。

使用Intellij IDEA 12.1.6和13.0在jdk 1.6.0_39和1.6.0_45下尝试了lombok 1.12.2和0.9.3,没有任何lombok插件。

不得不手动从delomboked源复制生成的方法,并将lombok搁置,直到更好的时机。

更新

只有启用并行编译时才会出现这个问题。

提交问题: https://github.com/rzwitserloot/lombok/issues/648 < / p >

更新

mplushnikov于2016年1月30日评论道:

Intellij的更新版本 不再有这样的问题了。

.

.

.

更新

如果可能的话,我强烈建议从Java+Lombok切换到芬兰湾的科特林。 因为它已经从头开始解决了Lombok试图解决的所有Java问题

我还没有尝试使用Lombok -它是/是我清单上的下一个,但听起来Java 8给它带来了很大的问题,补救工作在一周前仍在进行中。我的来源是https://code.google.com/p/projectlombok/issues/detail?id=451

我遇到了Lombok杰克逊CSV的问题,当我将我的对象(java bean)编组到CSV文件时,其中的列重复,然后我删除了Lombok的@Data注释,编组工作正常。

还有长期维护的风险。首先,我建议阅读有关Lombok实际是如何工作的,例如,它的开发人员在这里的一些回答。

官方网站还包含缺点清单,包括Reinier Zwitserloot的这句话:

这完全是一种hack。使用非公共API。冒昧的选择(知道 在javac中运行的注释处理器将获得的实例 的内部实现 AnnotationProcessor(一个接口),它恰好有一对 用于获取活AST的额外方法).

在eclipse上,它可以说更糟糕(但更健壮)——java代理 用于将代码注入eclipse语法和解析器类, 这当然是完全非公共API和完全禁止的。

如果你可以用标准API做lombok做的事情,我就会做了 它是那样的,但你不能。尽管如此,为了它的价值,我开发了 Eclipse插件,用于运行在Java 1.6上的Eclipse v3.5 在运行于Java 1.5上的eclipse v3.4上进行任何更改都可以工作 所以它不是完全脆弱的

总之,虽然Lombok可以节省一些开发时间,但如果有一个不向后兼容的javac更新(例如漏洞缓解),Lombok可能会让您陷入旧版本的Java,而开发人员则会争先恐后地更新他们对那些内部api的使用。这是否是一个严重的风险显然取决于项目。

龙目岛很棒,但是……

Lombok打破了注释处理的规则,因为它不生成新的源文件。这意味着它不能与其他注释处理器一起使用,如果它们期望getter /setter或其他任何存在的东西。

注释处理在一系列回合中运行。在每一轮中,每个人都有机会跑步。如果在一轮结束后发现任何新的java文件,则开始下一轮。这样,如果注释处理器只生成新文件,那么它们的顺序就无关紧要了。由于lombok不生成任何新文件,因此不会启动新的回合,因此一些依赖于lombok代码的AP不能按预期运行。在使用mapstruct时,这对我来说是一个巨大的痛苦来源,而delombok-ing并不是一个有用的选项,因为它会破坏日志中的行号。

我最终破解了一个构建脚本,可以同时使用lombok和mapstruct。但我想放弃龙目岛,因为它太粗糙了——至少在这个项目中是这样。我一直在用龙目岛做其他东西。 更新到mapstruct+lombok:这两个库现在可以开箱即用。不过,对于其他注释处理器来说,这个问题仍然存在
我对Lombok的看法是,它只是为编写样板Java代码提供了快捷方式 当涉及到使用快捷方式来编写样板Java代码时,我会依赖IDE提供的这些功能——就像在Eclipse中,我们可以进入菜单Source > Generate Getters and Setters来生成getter和setter 我不会依赖于Lombok这样的库:

  1. 它用一种间接的替代语法(阅读@Getter@Setter等注释)污染了你的代码。我不会学习Java的替代语法,而是会切换到任何其他原生提供类似Lombok语法的语言。
  2. Lombok要求使用支持Lombok的IDE来处理您的代码。这种依赖为任何重要的项目带来了相当大的风险。开源Lombok项目是否有足够的资源来继续为各种可用Java IDE的不同版本提供支持?
  3. 开源的Lombok项目是否有足够的资源来继续为将来出现的新版本Java提供支持?
  4. 我还担心Lombok可能会带来与在运行时处理字节代码的广泛使用的框架/库(如Spring、Hibernate、Jackson、JUnit、Mockito)的兼容性问题。

总而言之,我不喜欢用龙目岛来“调味”我的爪哇。

我读了一些关于龙目岛的意见,实际上我在一些项目中使用它。

嗯,第一次接触龙目岛时,我的印象很差。几周后,我开始喜欢上它了。但几个月后,我发现了很多使用它的小问题。所以,我对龙目岛的最终印象并不是那么积极。

我这么想的理由是:

  • IDE插件依赖关系。IDE对Lombok的支持是通过插件实现的。即使在大多数时间工作良好,你总是被这些插件劫持,在ide和即使是语言版本的未来版本中进行维护(Java 10+将加速该语言的开发)。例如,我试图从Intellij IDEA 2017.3更新到2018.1,但我做不到,因为在实际的lombok插件版本上有一些问题,我需要等待插件更新…如果您想使用没有任何Lombok插件支持的替代IDE,这也是一个问题。
  • “发现用法”问题。。使用Lombok时,你看不到生成的getter、setter、构造函数、构建器方法等。因此,如果你打算找出IDE在项目中使用这些方法的位置,你不能只寻找拥有这些隐藏方法的类。
  • 如此简单,以至于开发人员不关心破坏封装。我知道在龙目岛这不是什么问题。但是我看到了开发人员不再控制哪些方法需要可见或不可见的更大趋势。因此,很多时候他们只是复制和粘贴@Getter @Setter @Builder @AllArgsConstructor @NoArgsConstructor注释块,而没有考虑类真正需要公开哪些方法。
  • Builder Obssession©。我发明了这个名字(滚开,马丁·福勒)。开玩笑的是,Builder很容易创建,即使类只有两个形参,开发人员也更喜欢使用@Builder而不是构造函数或静态构造函数方法。有时,他们甚至试图在lombok Builder中创建一个生成器,创建像MyClass.builder().name("Name").build().create()这样奇怪的情况。
  • 重构时的障碍。例如,如果你正在使用@AllArgsConstructor,并且需要在构造函数上再添加一个参数,IDE不能帮助你在实例化类的所有地方(主要是测试)添加这个额外的参数。
  • 将龙目岛与具体方法混合。您不能在所有场景中都使用Lombok来创建getter/setter等。因此,您将在代码中看到这两种方法的混合。一段时间后你会习惯这一点,但感觉像是对语言的一种hack。

就像另一个回答说的,如果您对Java的冗长感到愤怒,并使用Lombok来处理它,那么可以尝试Kotlin。