代码之家  ›  专栏  ›  技术社区  ›  Mauli

cglib有替代品吗[[关闭]

  •  54
  • Mauli  · 技术社区  · 16 年前

    5 回复  |  直到 16 年前
        1
  •  108
  •   bric3    10 年前

    ASM

    JVMS ASM 4 guide

    然而,如果你需要完全控制,ASM是你的首选武器。

    Byte Buddy

    • ByteBuddy似乎没有其他库的缺点
    • 高度可配置
    • benchmark code )
    • 类型安全fluent API
    • Javassist建议或定制的插装代码是基于普通的 String

    • 注释驱动(灵活)

      用户回调可以配置注释,允许在回调中接收所需的参数。

    • 作为代理人提供

    • 有很好的记录
    • 很多例子
    • Android DEX支持

    Oracle Duke's choice award . 在这个时候,它刚刚到达 1.0.0 milestone ,这是相当大的成就。

    请注意 CGLIB by Byte Buddy 在版本2.1.0中。

    Javassist

    ProxyFactory 相当于CGLIB的 Enhancer 也有一些缺点,下面列举几个:

    • 不完全支持桥接方法(即为协变返回类型生成的方法)
    • ClassloaderProvider
    • 没有扩展点,而且几乎所有感兴趣的方法都是私有的,如果我们想改变某些行为,这是很麻烦的
    • 代理工厂 .

    • 方面代码是用一个普通的Java字符串编写的 编译
    • 无类型检查
    • 没有泛型
    • 无自动装箱

    另外,Javassist被认为比Cglib慢。这主要是由于它的方法是读取类文件,而不是像CGLIB那样读取加载的类。以及 implementation 它本身很难被解读为公平;如果需要对Javassist代码进行更改,那么很有可能会破坏某些东西。

    github circa 2013 似乎已经被证明是有用的,因为它显示了来自社区的定期提交和请求。

    这些限制仍然存在于版本3.17.1中。版本已经升级到3.20.0版本,但Javassist在支持Java8方面似乎仍然存在问题。

    JiteScript

    JiteScript看起来确实是一个很好地为ASM构建DSL的新工具,它基于最新的ASM版本(4.0)。代码看起来很干净。

    但是

    Proxetta

    这是一个相当新的工具,但它提供了迄今为止最好的 人类 应用程序编程接口。它允许不同类型的代理,如子类代理(cglib方法)或编织或委托。

    虽然,这是一个相当罕见的,没有信息存在,如果它运作良好。在处理字节码时,需要处理的角落太多了。

    AspectJ

    AspectJ是一个非常强大的 面向方面编程 (仅限)。AspectJ操纵字节码来实现它的目标,这样您就可以用它来实现您的目标。但是,这需要在编译时进行操作;spring通过代理在加载时提供自版本的编织 2.5 , 4.1.x .

    CGLIB

    关于CGLIB的一个词,自从这个问题被问到之后,它已经被更新了。

    CGLIB的速度相当快,这也是CGLIB仍然存在的主要原因之一,同时CGLIB的工作效率几乎比目前(2014-2015年)的任何替代方案都要好。

    一般来说,允许在运行时重写类的库必须避免在重写相应的类之前加载任何类型。因此,它们不能使用要求加载反射中使用的任何类型的javareflectionapi。相反,它们必须通过IO读取类文件(这是一个性能破坏器)。例如,这使得Javassist或Proxetta明显慢于Cglib,Cglib只是通过反射API读取方法并覆盖它们。

    然而,CGLIB不再处于积极的开发之中。有最近的版本,但这些变化被许多人认为是微不足道的,大多数人从来没有更新到版本3,因为CGLIB引入了一些 severe bugs 版本3.1修复了版本3.0的许多问题(自从版本4.0.3 Spring框架重新打包之后) version 3.1

    另外,CGLIB源代码也相当有用 poor quality 这样我们就不会看到新的开发人员加入CGLIB项目。要了解CGLIB的活跃性,请参阅他们的 mailing list .

    请注意,以下是 proposition on the guice mailing list ,CGLIB现在在 github 为了使社区能够更好地帮助项目,它似乎正在工作(多个提交和拉请求、ci、更新的maven),但大多数问题仍然存在。

    目前正在开发3.2.0版本,他们将精力集中在Java8上,但到目前为止,想要支持Java8的用户必须在构建时使用技巧。但进展非常缓慢。

    众所周知,CGLIB仍然受到PermGen内存泄漏的困扰。但其他项目可能已经这么多年没有经过实战考验了。

    Compile time annotation Processing

    当然,这不是运行时,而是生态系统的重要组成部分,大多数代码生成使用不需要运行时创建。

    这是从Java 5开始的,Java 5附带了单独的命令行工具来处理注释: apt ,并从Java6开始将注释处理集成到Java编译器中。

    有时需要显式地传递处理器,现在使用 ServiceLoader 方法(只需添加此文件 META-INF/services/javax.annotation.processing.Processor 编译器可以自动检测注释处理器。

    这种代码生成方法也有缺点,需要大量的工作和对Java语言的理解,而不是字节码。这个API有点麻烦,作为编译器中的插件,必须非常小心,使此代码成为最具弹性和用户友好的错误消息。

    这里最大的优点是它避免了运行时的另一个依赖关系,可以避免permgen内存泄漏。一个人可以完全控制生成的代码。

    在里面 2002

    它定义了关于代码生成的新标准,但现在不再是了,因为环境和需求已经改变了,标准和目标也改变了。

    JVM已经改变,并且将在最近和将来的Java(7/8/9/10)版本(invokedynamic、default方法、值类型等)中改变。ASM定期升级其API和内部构件以跟踪这些更改,但CGLIB和其他人尚未使用它们。

    截至2015年, 字节伙伴 虽然是新来的 提供最吸引人的 销售

        2
  •  10
  •   Bozho    16 年前

    Javassist .

    如果你需要做代理,看看 commons-proxy

        3
  •  10
  •   CurtainDog    16 年前

    ASM ,我相信cglib会用到它。虽然级别很低,但文档 明亮的 一旦你习惯了,你就可以飞了。

        4
  •  4
  •   FoxyBOA    16 年前

    我觉得用它更有意义 Javassist 而不是cglib。例如,javasist与cglib不同,可以完美地处理签名jar。另外,像Hibernate项目 decided to stop using cglib in favor of Javassist .

        5
  •  0
  •   jbaliuka    12 年前

    目前我看不到使用它的理由,我不再维护这个库(除了我的遗留应用程序的错误修复)。 实际上,我见过的所有CGLIB用例都是现代编程中的反模式。 通过任何JVM脚本语言(如groovy)实现相同的功能应该很简单。