运行时AOP vs 编译时AOP

17

这两种AOP框架有什么优缺点?我正在使用Unity作为我的AOP框架,但我认为像PostSharp这样的编译时AOP框架可能比运行时AOP框架性能更好?似乎运行时AOP框架使用反射来实现注入。

这两种AOP框架的优缺点在于它们的实现方式。编译时AOP框架如PostSharp将切面代码编织到目标程序集中,因此它可以提供更好的性能和较少的运行时开销。然而,运行时AOP框架如Unity使用反射动态地注入切面代码,因此它更加灵活和可扩展。

1个回答

58
  • 我不是.NET开发人员,但我了解Java生态系统中AOP领域,尤其是AspectJ和Spring AOP。基本上有四种类型的方面织入:
  • 源代码织入: 将方面代码作为源代码语句注入到应用程序源代码中。这是某种预处理器方法。目前在Java世界中没有任何AOP框架使用此方法,但在AOP早期曾经有过。
    • 优点是在运行时完全独立于任何运行时库或特殊的AOP编译器,如果做得正确。
    • 缺点是源代码膨胀并且需要进行预处理/代码生成步骤才能进行编译。您始终需要生成的源代码进行调试。
  • 编译时织入: 使用特殊编译器将方面代码编织到您的应用程序中。
    • 优点是对方面织入没有运行时开销。您唯一需要的是类路径上的一个小型运行时库。
    • 缺点是您不能延迟决定是否要在运行时将方面编织到您的应用程序中。但只有在处理不需要所有时间的调试或跟踪方面时才会出现问题。另一个缺点是此方法仅适用于您控制的代码,即您需要具有源代码。它不适用于第三方库。
  • 二进制织入: 在编译后而不是在编译期间将方面代码编织到现有类文件中。
    • 优点是它也适用于您没有源代码的第三方代码。此方法还可以与编译时织入混合使用。您还可以避免加载时织入的开销(请参见下文)。
    • 缺点类似于编译时织入:一旦将方面编织到代码中,就无法撤消它,仅通过像if()这样的切入点来停止其执行。但是这可能非常有效。
  • 加载时织入(LTW): 在VM /容器启动时提前加载织入代理/库。它会得到一个配置文件,其中包含描述应将哪些方面编织到哪些类中的规则。
  • 优点是您可以动态决定是否以及如何编织,如果是通过字节码转换而不是通过动态代理或反射(请参见下文),则生成的字节码与通过编译时或二进制编织创建的字节码同样有效。另一个优点是,就像二进制编织一样,它也适用于您自己的代码以及第三方代码,只要编织代理能够“看到”它,即它发生在子类加载器中。
  • 缺点是应用程序启动期间的一次编织开销,因为编织是在类加载时进行的。
  • 基于代理的LTW:Spring AOP使用此特殊的LTW形式,而AspectJ使用上面列出的前3种形式。它通过为切面目标创建动态代理(即子类或接口实现)来工作。
    • 除了你所选择的框架(例如Spring)可能支持它之外,我想不出任何特殊的优点。
    • 缺点是受限于公共的非静态方法和由于基于代理的方法导致的运行时开销。它也无法捕获内部方法调用,即当代理类调用自己的某个方法时,这些调用不会被代理捕获。不支持特殊类型的切入点,例如构造函数拦截、成员变量读取/写入访问等等,使其更像是"AOP lite"方法。但对于您的目的可能已经足够。
  • 通常,像AspectJ这样的良好切面编译器会创建非常高效的字节码,并且在运行时并不过多地依赖反射。如果您所选择的切面框架确实依赖于反射,则可能并不是非常快速。但是根据您使用方面的频率,也许它已经足够快了。

    可能我已经写得太多了,但我也可以写更多。这就是为什么我现在要停下来的原因。此外,这种问题并不适合StackOverflow,因为它可能会引起哲学讨论和基于观点的争论。即便如此,我希望自己能够相当客观/中立。


    Amir,你可以通过阅读文档来了解更多关于AspectJ的知识。我建议你尝试使用它,而不是自问一些理论问题。至于第二个问题,作为开发人员,你可以决定要使用哪种类型的织入。AspectJ没有任何操作,除非你相应地配置了构建环境。 - kriegaex
    @kriegaex AspectJ编译器与Java编译器相比有什么缺点吗?假设我们使用编译时织入并且由于AspectJ编译器而遇到问题。在无法修复AspectJ编译器的情况下,我们将不得不进行大量更改以使事情再次正常工作。简而言之,编译时织入似乎是最佳选择,但AspectJ编译器似乎是一个破坏者。你对此有何看法? - hrzafer
    我的观点是:有些人能够为每个问题找到解决方案,而另一些人则在每个解决方案中找到问题。此外,AspectJ编译器是Eclipse Java编译器的一个经常更新的分支,维护得非常好。与Oracle JVM相比,更容易引起维护者的注意。我的建议是:不仅要看到风险,也要看到机会。我认为这里没有任何“交易破坏者”。 - kriegaex
    请问是否可以在单个方法上使用CTW和LTW来处理不同的注解?也就是说,为某些注解配置LTW,而为其他注解配置CTW。最近我尝试这样做时遇到了问题,只能将所有注解都配置为LTW。非常感谢您的帮助。 - shiva
    请不要在一个五年以上的问题下跟帖,而是创建一个新问题并选择正确的标签,那么我会自动收到通知。您可以从新问题中链接到这个问题。但是当您提出新问题时,请提供一个MCVE,而不仅仅是两个句子。我无法调试散文。"我尝试了X,它不起作用"不能算作一个好问题。 - kriegaex
    显示剩余2条评论

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