使用Project Lombok是否安全?

The*_*eLQ 422 java lombok

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

但是,我担心从长远来看,这将是一个令人遗憾的决定.##Java Freenode当我提到它时,Flamewars会在频道中爆发,提供代码片段会让可能的帮助者感到困惑,人们会抱怨缺少JavaDoc,而且未来的委托人可能会将其全部删除.我真的很喜欢积极的,但我担心的是消极的.

那么:在任何项目中使用Lombok都是安全的吗?积极影响是否值得消极?

Sne*_*kse 818

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

如果您有一个带注释的类@Data,它将根据字段名称为您生成getter和setter.如果你在另一个类中使用其中一个getter,那么确定该字段命名不佳,它将找不到那些getter和setter的用法,并用新名称替换旧名称.

我想这必须通过IDE插件而不是通过Lombok来完成.

更新(2013年1月22日)
使用龙目岛3个月后,我仍然推荐它用于大多数项目.但是,我确实找到了与上面列出的相似的另一个缺点.

如果你有一类,说MyCompoundObject.java的是有2名成员,都与注解@Delegate,说myWidgetsmyGadgets,当你调用myCompoundObject.getThingies()从另一个类,这是不可能知道它是否委托给Widget或者Gadget因为你再也不能在IDE中跳转到源.

使用Eclipse"Generate Delegate Methods ..."为您提供相同的功能,同样快速并提供源跳转.缺点是它使用样板代码使您的源变得混乱,重点放在重要的东西上.

更新2(2013年2月26日)
经过5个月,我们仍在使用龙目岛,但我还有其他一些烦恼.当您尝试熟悉新代码时,缺少声明的getter和setter可能会变得很烦人.

例如,如果我看到一个被调用的方法,getDynamicCols()但我不知道它是什么,我有一些额外的障碍来跳转来确定这个方法的目的.一些障碍是龙目岛,一些是缺乏Lombok智能插件.障碍包括:

  • 缺乏JavaDocs.如果我对该字段进行javadoc,我希望getter和setter将通过Lombok编译步骤继承该javadoc.
  • 跳转到方法定义会跳转到类,但不会跳转到生成getter的属性.这是一个插件问题.
  • 显然,除非生成或编码方法,否则无法在getter/setter中设置断点.
  • 注意:此参考搜索不是我最初认为的问题.您确实需要使用启用Outline视图的透视图.大多数开发人员都不是问题.我的问题是我正在使用Mylyn过滤我的Outline视图,所以我没有看到方法. 缺乏参考搜索.如果我想看看谁在调用getDynamicCols(args...),我必须生成或编码setter才能搜索引用.

更新3(2013年3月7日)
我想在Eclipse中学习使用各种方法.实际上,您可以在Lombok生成的方法上设置条件断点(BP).使用该Outline视图,可以右键单击该方法Toggle Method Breakpoint.然后,当您点击BP时,可以使用调试Variables视图查看生成的方法命名参数(通常与字段名称相同),最后使用Breakpoints视图右键单击BP并选择Breakpoint Properties...添加条件.尼斯.

更新4(2013年8月16日)
当您在Maven pom中更新Lombok依赖项时,Netbeans不喜欢它.该项目仍在编译,但文件因为编译错误而被标记,因为它无法看到Lombok正在创建的方法.清除Netbeans缓存可以解决问题.不确定是否存在Eclipse中的"Clean Project"选项.小问题,但想让它知道.

更新5(2014年1月17日)
龙目岛并不总是与Groovy,或至少groovy-eclipse-compiler.您可能必须降级编译器的版本. Maven Groovy和Java + Lombok

更新6(2014年6月26日)
一句警告.龙目岛有点上瘾,如果你在一个你不能因某些原因使用它的项目上工作,它会让你烦恼不已.你最好永远不要使用它.

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

从v1.14开始,@Delegate注释已被降级为实验状态.详细信息记录在他们的网站上(Lombok Delegate Docs).

问题是,如果您使用此功能,您的退出选项是有限的.我看到的选项如下:

  • 手动删除@Delegate注释并生成/ 手动编写代理代码.如果您在注释中使用属性,这会有点困难.
  • Delombok具有@Delegate注释的文件,可能会添加到您想要的注释中.
  • 永远不要更新Lombok或维护分叉(或使用体验功能).
  • Delombok整个项目并停止使用Lombok.

据我所知,Delombok没有删除注释子集的选项 ; 它至少对于单个文件的上下文是全有或全无.我开了一张票,用Delombok旗帜请求这个功能,但我不希望在不久的将来.

更新8(2014年10月20日)
如果它是你的选择,Groovy提供龙目岛的大部分相同的好处,以及其他功能的船载,包括@Delegate.如果你认为你很难将这个想法卖给那些权力,那就看一下@CompileStatic或者@TypeChecked注释,看看它是否有助于你的事业.实际上,Groovy 2.0版本的主要关注点是静态安全性.

更新9(2015年9月1日)
龙目岛仍在积极维护和增强,这预示着采用的安全水平.该@Builder注解是我最喜欢的新功能之一.

更新10(2015年11月17日)
这似乎与OP的问题没有直接关系,但值得分享.如果您正在寻找可以帮助您减少所编写的样板代码量的工具,您还可以查看Google Auto - 特别是AutoValue.如果你看一下他们的幻灯片,列表龙目岛作为他们试图解决的问题的可能解决方案.他们为龙目岛列出的缺点是:

  • 插入的代码是不可见的(你不能"看到"它生成的方法)[编号 - 实际上你可以,但它只需要一个反编译器]
  • 编译器黑客是非标准和脆弱的
  • "在我们看来,你的代码不再是真正的Java"

我不确定我对他们的评价多少赞同.考虑到幻灯片中记录的AutoValue的缺点,我将坚持使用Lombok(如果Groovy不是一个选项).

更新11(2016年2月8日)
我发现Spring Roo有一些类似的注释.我有点惊讶地发现Roo仍然是一个东西,找到注释的文档有点粗糙.去除也不像de-lombok那么容易.龙目岛似乎是更安全的选择.

更新12(16年2月17日)
虽然试图找出为什么可以安全地为我正在进行的项目引入龙目岛的理由,但我找到了一块金v1.14- 添加了- 配置系统!这意味着您可以配置项目以禁止您的团队认为不安全或不合需要的某些功能.更好的是,它还可以使用不同的设置创建特定于目录的配置.这太棒了.

更新13(2016年10月4日)
如果这件事对你很重要,Oliver Gierke认为将Lombok添加到Spring Data Rest是安全的.

更新14(17年9月26日)
正如@gavenkoa在关于OP问题的评论中指出的那样,JDK9编译器支持尚不可用(问题#985).听起来这对龙目团队来说并不是一个简单的解决办法.

更新15(18年3月26日)
龙目岛更改日志显示从v1.16.20开始" 尽管#985仍然打开,但现在可以在JDK1.9上编译 lombok" .

但是,为适应JDK9而进行的更改需要进行一些重大改变; 所有与配置默认值的更改隔离.关于他们引入了重大变化,这有点令人担忧,但该版本仅提升了"增量"版本号(从v1.16.18升至v1.16.20).由于这篇文章是关于安全性的,如果你有一个yarn/npm类似的构建系统自动升级到最新的增量版本,你可能会陷入一种粗鲁的觉醒.

更新16(1919年1月9日)

似乎JDK9问题已经解决,Lombok与JDK10一起工作,甚至JDK11也是如此.

有一件事我注意到,从安全方面来说,这是因为从v1.18.2到v1.18.4的更改日志列出了两个项目BREAKING CHANGE!我不确定在semver"补丁"更新中如何发生突破性变化.如果您使用自动更新修补程序版本的工具,则可能会出现问题.

  • 谢谢我认为这是OP真正想要的信息而不是哲学反应. (46认同)
  • `更新6`感觉很像Scala :) (14认同)
  • 我非常喜欢你随时间变化的更新.特别是对于这种风格的问题/回应,它确实有帮助. (6认同)
  • @mauhiz和Groovy.如果我不得不在一个我无法使用Groovy或Scala进行测试的地方工作,我可能会在很短的时间内退出. (5认同)
  • 似乎Java 9支持现在可用.你可以更新你的答案./sf/ask/2906435801/ (4认同)
  • 最好的答案我到目前为止已经阅读过了 (4认同)
  • 这是名人堂的答案之一,应该是公认的答案。感谢您的投入! (3认同)
  • 关于SO的25个答案就在这里. (2认同)
  • Lombok项目有一个新的测试版,似乎解决了大多数java 9问题. (2认同)
  • 这听起来像一本小说。 (2认同)
  • 好答案!+1可随时了解龙目岛各地的最新动态。 (2认同)

Ste*_*n C 182

听起来您已经确定Project Lombok为您提出的新项目提供了重要的技术优势.(从一开始就要清楚,我对Lombok项目没有特别的看法,无论如何.)

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

你提到这些潜在的问题:

当我提到它时,Flamewars会在## Java Freenode频道中爆发,

简单.忽略/不参加火焰战争,或者干脆提及龙目岛.

提供代码片段会混淆可能的帮助者,

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

人们会抱怨缺少JavaDoc,

这是他们的问题.没有人在正确的思想中试图将他们组织的源代码/文档规则严格地应用于第三方开源软件.项目团队应该可以自由设置适合所用技术的项目源代码/文档标准.

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

而且未来的通勤者可能会将其全部删除.

那不是!如果商定的项目策略是使用Lombok,那么那些无偿地删除代码的委员应该受到惩罚,并在必要时撤销其提交权.

当然,这假设您已经从利益相关者那里获得了支持......包括开发人员.它假设你准备好争辩你的事业,并妥善处理不可避免的不同意见.

  • 我会说bean吸气剂/孵化器的javadoc弊大于利.这些方法遵循一个易于理解的约定,不需要添加到javadoc; 这只会增加噪音.只有当他们做出意想不到的事情时才会向getter和setter添加文档,即当他们有副作用时. (172认同)
  • 作为一名Lombok开发人员,我可以说生成javadoc在技术上是可行的.如果您有任何明智的想法如何实施它,请参与谷歌小组.我的意思是,仅生成标准文本并不是那么有用.像getFoo一样,返回foo,setFoo设置foo?这有什么用呢? (75认同)
  • @VGR我同意你所说的一般,但在这种特定情况下更好的解决方案是更好的命名,而不是评论.即`getCreationDate`,`getDueDate`.命名尽可能胜过评论. (21认同)
  • @GaryF真的吗?如何记录值是否为null?或者数值的允许范围?或者String值的允许长度和/或格式?或者String值是否适合呈现给最终用户?或者记录财产的实际含义,何时其名称无法完整解释?([JList.getLayoutOrientation](https://docs.oracle.com/javase/8/docs/api/javax/swing/JList.html#getLayoutOrientation--)和[JList.setLayoutOrientation](https:// docs.想到oracle.com/javase/8/docs/api/javax/swing/JList.html#setLayoutOrientation-int-).) (13认同)
  • 我刚刚意识到javadoc注释可能指的是如果你为你的lomboked代码生成javadoc,getter和setter根本就不显示.解决这个问题的方法是在你的delomboked代码上运行javadoc. (8认同)
  • @VGR这些是一些有用的反例,在哪里,是的,我们可能想要一些Javadoc.我一般都会说,大多数getter/setter的Javadoc都是噪音:自动生成的文档主要用于生成或设置属性.请记住上下文:Lombok用于在简单的属性样式字段上生成getter/setter,而不是在应用其他验证逻辑的位置. (3认同)
  • @GaryF这是噪音,因为开发人员实在太懒了.特别是业务对象需要文档.我已经忘记了我所处理的bean类的数量,其属性对于没有几个月或几年领域特定知识的人来说没有意义.大多数开发人员会使用javadoc来记录`getDate()`,只是说`获取此对象的日期`,这似乎支持你的论点,但实际上,开发人员应该已经解释了*日期的用途.(提交日期?创建日期?到期日期?到期日期?) (3认同)
  • 在小型开源项目中呢?你对团队的同意非常好,但我也对1-2人OS项目的观点感到好奇 (2认同)

Ken*_*net 114

继续使用Lombok,如果有必要,你可以随后"delombok"你的代码http://projectlombok.org/features/delombok.html

  • 在这种特殊情况下,我将"+1 for delombok"解释为"万岁delombok".我喜欢. (7认同)
  • @fastcodejava当你说"+1 for x"时,x应该是列出的点之一而不是唯一的点:) (5认同)
  • 对于那些想“好吧,我会尝试一下 Lombok,如果我不喜欢它,我就直接使用 Delombok”的人来说:三思而后行。运行 Delombok 是一个痛苦的过程。生成的代码将像 Lombok 一样工作......但它也将是一团糟。 (2认同)

Tim*_*Tim 73

就个人而言(因此主观上)我发现使用Lombok使我的代码更能表达我与IDE /自己的复杂方法(例如hashcode和equals)的实现相比我想要实现的目标.

使用时

@EqualsAndHashCode(callSuper = false, of = { "field1", "field2", "field3" })
Run Code Online (Sandbox Code Playgroud)

与任何IDE /自己的实现相比,保持Equals和HashCode一致并跟踪评估哪些字段要容易得多.当您仍然定期添加/删除字段时尤其如此.

这同样适用于所述@ToString注释和它的参数,其清楚地传达关于包括/排除字段,吸气剂或字段访问和阉羊或不调用使用所期望的行为super.toString().

再次通过使用@Getter或注释整个类@Setter(AccessLevel.NONE)(并且可选地覆盖任何不同的方法),可以立即清楚哪些方法可用于字段.

好处还在继续......

在我看来,这不是关于减少代码,而是关于清楚地传达你想要实现的东西,而不是必须从Javadoc或实现中弄清楚它.简化代码使得更容易发现任何发散方法实现.

  • 并补充一点:切换到Lombok实际上允许解决过去由于不匹配的equals/hashCode实现而导致的一些错综复杂的错误,以及在添加字段时忘记更新现在生成的方法的情况.这些潜在的好处应该能够平衡你提到的大多数负面因素. (21认同)

twe*_*mon 23

龙目岛很棒,但......

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

注释处理在一系列轮次中运行.在每一轮中,每一轮都会轮到跑.如果在回合完成后找到任何新的java文件,则开始另一轮.这样,如果注释处理器仅生成新文件,则它们的顺序无关紧要.由于lombok不会生成任何新文件,因此不会启动新轮次,因此某些依赖于lombok代码的AP无法按预期运行.在使用mapstruct时,这对我来说是一个巨大的痛苦来源,并且delomboking不是一个有用的选项,因为它会破坏日志中的行号.

我最终攻击了一个构建脚本来使用lombok和mapstruct.但我想放弃lombok,因为它至少是hacky - 至少在这个项目中.我总是在其他东西中使用lombok.


Dhe*_*rik 20

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

好吧,在与龙目岛的第一次接触中,我的印象很糟糕.几周后,我开始喜欢它了.但几个月后我发现了很多使用它的小问题.所以,我对龙目岛的最终印象并不那么积极.

我以这种方式思考的理由:

  • IDE插件依赖.IDE对Lombok的支持是通过插件实现的.即使在大多数情况下工作良好,你仍然是这个插件的人质,可以在IDE的未来版本中维护,甚至语言版本(Java 10+将加速语言的开发).每个例子,我试图从Intellij IDE 2017.3更新到2018.1,我不能这样做,因为实际的lombok插件版本存在一些问题,我需要等待插件更新...这也是一个问题,如果你我想使用一个没有任何Lombok插件支持的替代IDE.
  • '查找用法'问题..使用Lombok,您看不到生成的getter,setter,构造函数,构建器方法等.因此,如果您计划通过IDE了解项目中正在使用的这些方法,则不能只执行此操作寻找拥有这种隐藏方法的类.
  • 很容易让开发人员不关心打破封装.我知道龙目岛并不是一个真正的问题.但是我看到开发人员更不愿意再控制哪些方法需要显示与否.因此,很多时候他们只是在@Getter @Setter @Builder @AllArgsConstructor @NoArgsConstructor不考虑类真正需要暴露的方法的情况下复制和粘贴注释.
  • 生成器痴迷 ©.我发明了这个名字(下车,Martin Fowler).除此之外,Builder很容易创建,即使一个类只有两个参数,开发人员更喜欢使用@Builder而不是构造函数或静态构造函数方法.有时他们甚至尝试在lombok Builder中创建一个Builder,创建奇怪的情况,比如MyClass.builder().name("Name").build().create().
  • 重构时的障碍.如果您正在使用,例如,@AllArgsConstructor并且需要在构造函数上添加一个参数,则IDE无法帮助您在实例化该类的所有位置(主要是测试)中添加此额外参数.
  • 将龙目岛与具体方法相结合.您不能在所有场景中使用Lombok来创建getter/setter/etc. 因此,您将在代码中看到这两种方法混合在一起.一段时间后你会习惯这个,但感觉就像是语言的黑客.

就像另一个回答所说的那样,如果你对Java的冗长程度感到愤怒并使用龙目岛处理它,请尝试Kotlin.

  • 我会说去Kotlin或者继续使用普通的Java.通过不输入java代码,您可能会花费更多时间来处理Lombok问题. (8认同)
  • 那些仅仅因为冗长而讨厌 Java 的人就是他没有让他的代码变得不那么冗长的错...... (3认同)

dsk*_*rvk 17

还存在长期维护风险.首先,我建议你阅读有关龙目岛的实际工作原理,例如,从它的开发者一些答案在这里.

官方网站还包含一系列缺点,包括Reinier Zwitserloot的引用:

这完全是黑客攻击.使用非公共API.放肆的演员(知道在javac中运行的注释处理器将获得JavacAnnotationProcessor的实例,这是AnnotationProcessor(一个接口)的内部实现,这恰好有几个额外的方法用于获取实时AST) .

在eclipse上,它可以说更糟(但更强大) - 一个java代理用于将代码注入到eclipse语法和解析器类中,这当然完全是非公共API,完全不受限制.

如果你可以使用标准API做lombok所做的事情,我会这样做,但你做不到.尽管如此,为了它的价值,我开发了在java 1.6上运行的eclipse v3.5的eclipse插件,并且没有对它在java 1.5上运行的eclipse v3.4进行任何更改,所以它并不是完全脆弱的.

总而言之,虽然Lombok可以为您节省一些开发时间,但如果存在非向后兼容的javac更新(例如,漏洞缓解),Lombok可能会让您遇到旧版Java,而开发人员则争相更新其使用内部API.这是否是一个严重的风险显然取决于项目.

  • 好吧,如果你不能再使用Lombok了,只需运行delombok并在没有它的情况下继续开发. (8认同)
  • 这就像学习驾驶戴眼镜然后在驾驶考试之前丢失它们.如果您的团队习惯使用Lombok的代码并且由于突破性的变化而突然被迫改变他们的流程,这将对正在进行的项目产生巨大影响.是不是更好地完全避免这种风险并使用不依赖于未记录的功能的框架或像Scala这样提供相同功能的框架? (3认同)

小智 15

我在几乎所有的项目中都使用了龙目岛一年,但遗憾的是将其删除了.一开始它是一种非常干净的开发方式,但为新团队成员建立开发环境并不容易和直截了当.当它成为一个头痛我刚刚删除它.但这是一项很好的工作,需要更简单的设置.

  • 你能详细说明头痛吗? (27认同)
  • 我认为设置新开发人员最困难的部分是意识到_你需要设置Lombok.没有消息说"龙目岛尚未设置"或类似的东西.相反,你会得到像"setFoo"这样奇怪的消息.如果Lombok教育不是您的新开发人员机上培训过程的一部分,那么将会出现重大混乱. (14认同)
  • Eclipse的设置非常简单.只是"java -jar lombok.jar". (2认同)
  • lombok idea插件(我使用版本0.13.16)最近引入了支持,以通知用户未配置注释处理器,并且还提供了指向配置设置部分的链接以启用apt。请参阅的屏幕截图。https://postimg.org/image/5tm2zzvkh/ (2认同)

sor*_*ito 15

我知道我已经迟到了,但我无法抗拒诱惑:任何喜欢龙目岛的人都应该看看Scala.您在Lombok中找到的许多好主意都是Scala语言的一部分.

关于你的问题:让你的开发人员尝试Lombok比Scala更容易.尝试一下,如果他们喜欢它,请尝试Scala.

就像免责声明一样:我也喜欢Java!

  • 也试试Kotlin (5认同)
  • @sinuhepop生成getter和setter看起来像Case Classes.不可变特性是Scala固有的,并且关于您自己的方法的丰富API也是内置的Scala特性. (2认同)

小智 11

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

  • 就ROI而言,集成非常简单,并且不需要更改其基本形式的代码.(只需在您的班级中添加一个注释)

  • 最后,如果你改变主意,你可以运行unlombok,或者让你的IDE创建这些setter,getters和ctors,(我认为一旦他们看到你的pojo变得有多清楚,就没有人会要求)


Vad*_*zim 10

想要使用lombok,@ToString但很快就会遇到Intellij IDEA中项目重建的随机编译错误.在增量编译成功完成之前,必须多次编译.

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

不得不从delomboked源手动复制生成的方法,并将lombok保留到更好的时间.

更新

仅在启用并行编译时才会出现此问题.

提起问题:https: //github.com/rzwitserloot/lombok/issues/648

更新

mplushnikov于2016年1月30日评论:

较新版本的Intellij不再存在此类问题.我想它可以在这里关闭.

更新

我强烈建议尽可能从Java + Lombok切换到Kotlin.因为它已经彻底解决了Lombok试图解决的所有Java问题.


San*_*dev 9

我对Lombok的看法是它只提供了编写bolilerplate Java代码的快捷方式.
当使用快捷方式编写bolilerplate 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)中引入兼容性问题,这些框架/库在运行时与您的字节代码一起使用.

总而言之,我不希望用龙目岛"加强"我的Java.


Gug*_*upf 6

我遇到了LombokJackson CSV的问题,当我将我的对象(java bean)编组为CSV文件,列重复时,我删除了Lombok的@Data注释并编组工作正常.