运行时AOP与编译时AOP

All*_*ech 9 architecture aop

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

kri*_*aex 42

我不是.NET人,但我知道Java生态系统中的AOP世界,尤其是AspectJ和Spring AOP.基本上有四种类型的方面编织:

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

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

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