有cglib的替代品吗?
出于好奇,除了cglib之外,是否有任何(稳定)开源项目用于运行时Java代码生成?我为什么要使用它们?
回答:
回答:
“显示标记为“ java-asm”的问题”)
CGLIB和几乎所有其他库都建立在ASM之上,而ASM本身的作用很低。对于大多数人来说,这是一个阻止因素,因为您必须了解字节码和一些JVMS才能正确使用它。但是掌握ASM无疑是非常有趣的。但是请注意,尽管有
ASM4指南,但在API的某些部分中,javadoc文档可能非常简洁(如果存在的话),但仍在改进中。它紧密遵循JVM版本以支持新功能。
但是,如果您需要完全控制,ASM是您的首选武器。
该项目定期更新; 在2015年5月15日发布此编辑版本5.0.4时。
回答:
Byte Buddy是一个相当新的库,但是提供了CGLIB或Javassist提供的任何功能以及更多功能。Byte
Buddy可以完全自定义到字节代码级别,并带有一种表达性强的领域特定语言,允许非常可读的代码。
- 它支持所有JVM字节码版本,包括有关默认方法的某些操作码的Java 8语义更改。
- ByteBuddy似乎没有遭受其他库所具有的缺点的困扰
- 高度可配置
- 相当快(基准 代码)
- 类型安全的流利API
- 输入安全回调
Javassist的建议或自定义工具代码基于简单的代码,
String
因此无法在此代码中进行类型检查和调试,而ByteBuddy允许使用纯Java编写代码并因此进行类型检查并允许调试。
- 注释驱动(灵活)
用户回调可以配置有注释,以允许在回调中接收所需的参数。
- 可作为代理
漂亮的代理构建器允许ByteBuddy用作纯代理或附加代理。它允许不同的种类
- 很好的记录
- 很多例子
- 干净的代码,约94%的测试覆盖率
- Android DEX支持
该API的主要缺点也许是,对于初学者来说有点冗长,但它被设计为一种像代理代DSL一样的可选API;没有魔术或可疑的默认值。在处理字节码时,它可能是最安全,最合理的选择。同样,有多个示例和大量教程,这不是真正的问题。
在2015年10月,该项目获得了OracleDuke的选择奖。此时,它刚刚达到了1.0.0里程碑,这是一个很大的成就。
请注意,mockito已在2.1.0版中将ByteBuddy替换为CGLIB。
回答:
Javassist
Javassist的Javadoc比CGLIB更好。类工程API可以,但是Javassist也不完美。特别是,ProxyFactory
它等同于CGLIB的Enhancer
缺点,仅列举了一些缺点:
- 不完全支持Bridge方法(即针对协变返回类型生成的方法)
ClassloaderProvider
是一个静态字段,那么它适用于同一类加载器中的所有实例- 自定义命名可能会受到欢迎(带签名罐子的支票)
- 没有扩展点,几乎所有感兴趣的方法都是私有的,如果我们要更改某些行为,这将很麻烦
- 尽管Javassist支持类中的注释属性,但中不支持它们
ProxyFactory
。
在面向方面方面,可以将代码注入代理中,但是Javassist中的这种方法是有限的,并且容易出错:
- 方面代码以纯Java字符串 编写 ,并以操作码 编译
- 没有类型检查
- 没有泛型
- 没有lambda
- 没有自动装箱
Javassist也被认为比Cglib慢。这主要是由于其读取类文件的方法,而不是像CGLIB这样读取已加载的类的方法。而且实现本身很难理解为公平;
如果需要更改Javassist代码,则有很多机会破坏某些东西。
Javassist也遭受了不活动的困扰,他们被证明在2013年左右迁移到github似乎很有用,因为它显示了定期的提交和来自社区的请求。
这些限制仍然存在于3.17.1版中。该版本已被升级到3.20.0版本,但是Javassist似乎仍然对Java 8支持存在问题。
回答:
JiteScript看起来确实是为ASM精心设计DSL的新作品,它基于最新的ASM版本(4.0)。该代码看起来很干净。
该项目尚处于早期阶段,因此可以更改API /行为,而且文档非常糟糕。并更新稀缺,如果不放弃。
回答:
乔德
这是一个相当新的工具,但是它提供了迄今为止最好的 人工 API。它允许使用不同类型的代理,例如子类代理(cglib方法)或编织或委派。
尽管这是相当少见的,但如果运作良好,则没有任何信息。在处理字节码时,有很多特殊情况需要处理。
回答:
AspectJ
AspectJ是用于
的非常强大的工具(仅)。AspectJ通过操纵字节码来实现其目标,以便您可以由此实现目标。但是,这需要在编译时进行操作。从2.5版4.1.x开始,Spring通过代理在加载时进行编织。
回答:
cglib
自问这个问题以来,有关CGLIB的词汇已更新。
CGLIB的运行速度非常快,这是它仍然存在的主要原因之一,而且CGLIB的运行几乎比现在(2014-2015年)的任何替代产品都要好。
一般来说,允许在运行时重写类的库必须避免在重写相应类之前加载任何类型。因此,它们不能使用Java反射API,而Java反射API要求加载反射中使用的任何类型。相反,他们必须通过IO(这是性能破坏者)读取类文件。例如,这使得Javassist或Proxetta比Cglib慢得多,后者仅通过反射API读取方法并覆盖它们。
但是,CGLIB不再处于积极开发中。 有最新版本,但是许多人认为这些更改微不足道,并且大多数人从未更新到版本3,因为CGLIB
在最新版本中引入了一些严重的错误,但实际上并没有建立信心。3.1版解决了3.0版的许多问题(因为4.0.3版Spring框架重新打包了3.1版)。
而且,CGLIB源代码的质量很差,因此我们看不到新的开发人员加入CGLIB项目。要了解CGLIB的活跃性,请参阅他们的邮件列表。
请注意,遵循guice邮件列表上的命题之后,CGLIB现在可以在github上使用,以使社区能够更好地帮助该项目,它似乎正在工作(多次提交和请求,ci,更新的maven),但仍然存在大多数问题。
目前,正在开发3.2.0版,并且他们将精力集中在Java 8上,但是到目前为止,想要Java 8支持的用户必须在构建时使用技巧。但是进展非常缓慢。
CGLIB仍然因PermGen内存泄漏而困扰。但是其他项目可能没有经过这么多年的战斗测试。
回答:
编译时注释处理
注释处理
当然,这不是运行时,而是生态系统的重要组成部分,大多数代码生成用法不需要创建运行时。
从Java 5开始,Java 5带有单独的命令行工具来处理批注:apt
,从Java 6开始,批注处理已集成到Java编译器中。
在某些时候,您需要显式地传递处理器,现在通过这种ServiceLoader
方法(只需将此文件添加META-
INF/services/javax.annotation.processing.Processor到jar中),编译器就可以自动检测注释处理器。
这种代码生成方法也有缺点,它也需要大量工作,并且需要理解Java语言而不是字节码。该API有点麻烦,并且因为它是编译器中的插件,因此必须格外小心,以使该代码成为最有弹性和用户友好的错误消息。
这里最大的好处是,它避免了运行时的另一个依赖关系,可以避免permgen内存泄漏。并且可以完全控制生成的代码。
回答:
在2002年
CGLIB定义了一个新的标准来轻松地操作字节码。当今我们拥有的许多工具和方法(CI,覆盖范围,TDD等)当时都不可用或尚未成熟。十多年来,CGLIB一直与时俱进;
这是一个相当不错的成就。与直接操作操作码相比,它的运行速度快且具有易于使用的API。
它定义了有关代码生成的新标准,但如今由于环境和要求已发生变化,因此不再存在,标准和目标也已发生变化。
JVM已更改,并将在最近和将来的Java(7/8/9/10)版本(调用动态,默认方法,值类型等)中更改。ASM定期升级他的API和内部组件以适应这些更改,但是CGLIB和其他人员尚未使用它们。
尽管注释处理越来越受青睐,但它不像运行时生成那样灵活。
截至2015年, 虽然 , 但它 为运行时生成提供了最引人注目的 卖点
。相当不错的更新速度,并且作者对Java字节码内部知识非常了解。
以上是 有cglib的替代品吗? 的全部内容, 来源链接: utcz.com/qa/407897.html