运行时AOP与编译时AOP

时间:2016-09-12 10:44:37

标签: architecture aop

这两种AOP框架的优点和缺点是什么?我正在使用Unity作为我的aop框架,但是我认为诸如postharp之类的编译时aop框架可能比运行时aop框架具有更好的性能?它看起来像运行时aop框架使用反射来实现注入。

1 个答案:

答案 0 :(得分:37)

我不是.NET人,但我了解Java生态系统中的AOP世界,特别是AspectJ和Spring AOP。基本上有四种类型的方面编织:

  • 源代码编织:Aspect代码作为源代码语句注入到您的应用程序源代码中。这是某种预处理器方法。 Java世界中没有AOP框架现在使用这种方法,但在AOP的早期曾经有过一些。
    • 如果操作正确,优点是任何运行时库或特殊AOP编译器在运行时都是完全独立的。
    • 在编译之前,缺点是膨胀的源代码和预处理/代码生成步骤。您始终需要生成的源代码进行调试。
  • 编译时编织:Aspect代码由特殊的编译器编织到您的应用程序中。
    • 优点是方面编织没有运行时开销。您唯一需要的是类路径上的小型运行时库。
    • 缺点是,如果要将方面完全编织到应用程序中,则无法推迟决策。但这在处理调试或跟踪不需要的方面时只是一个问题。另一个缺点是这种方法仅适用于您控制的代码,即您需要拥有源代码。它不适用于第三方库。
  • 二进制编织:在编译之后而不是在编译期间,会将代码编织到现有的类文件中。
    • 优点是它也适用于没有源代码的第三方代码。这种方法也可以与编译时编织混合使用。您还可以避免加载时织入的开销(见下文)。
    • 缺点类似于编译时编织:一旦将一个方面编织到代码中就不能取消应用,只需通过if()之类的切入点来停用它的执行。但这可能非常有效。
  • 加载时间编织(LTW):启动VM /容器时,会尽早加载编织代理程序/库。它获得一个配置文件,其中包含描述哪些方面应编入哪些类的规则。
    • 优点是你可以动态决定是否编织。如果通过字节码转换而不是通过动态代理或反射(见下文)完成,则生成的字节码与通过编译时或二进制编织创建的字节码同样有效。另一个优点是,就像二进制编织一样,它适用于您自己的代码以及第三方代码,只要编织代理可以"看到"它,即它发生在儿童类加载器中。
    • 缺点是应用程序启动期间的一次性编织开销,因为在进行类加载时进行编织。
  • 基于代理的LTW :这个特殊的LTW表单由Spring AOP使用,而AspectJ使用上面列出的前3个表单。它的工作原理是为方面目标创建动态代理(即子类或接口实现)。
    • 除了你选择的框架(例如Spring)可能支持它之外,我想不出任何特别的优势。
    • 由于基于代理的方法,缺点是公共,非静态方法和运行时开销的限制。它也不捕获内部方法调用,即当代理类调用其自己的方法之一时,因为代理不捕获这些调用。不支持特殊类型的切入点,例如构造函数拦截,成员变量读/写访问等等,这使得它更像是一个" AOP lite"做法。但它足以满足您的目的。

通常,像AspectJ这样的优秀方面编译器会创建非常高效的字节码,并且在运行时不会严重依赖于反射。如果您选择的方面框架确实依赖于反射,那么它可能不是很快。但也许它足够快,取决于你使用方面的重要程度。

可能我已经写了太多,但我可以写得更多。这就是我现在停下来的原因。此外,这类问题并不适合StackOverflow,因为它可以引发哲学讨论和基于意见的辩论。我希望即使如此,我也能保持相当客观/公正。

相关问题