【问题标题】:JAVA Aspect Oriented Programming- Runtime Aspect Weaving and Class Loading time aspect weavingJAVA Aspect Oriented Programming-运行时切面编织和类加载时间切面编织
【发布时间】:2014-05-13 18:32:23
【问题描述】:

我偶然看到一篇关于 AOP 的文章,其中提到 Aspect weaving 可以在编译时、类加载时和运行时发生。

在 java 中,我可以想象,也可以理解,方面编织在编译期间实际上是如何发生的。代理类是在类编译期间生成的(在项目上启用方面)。生成的字节码将具有代理代码。

但我仍然想知道在类加载时编织和运行时编织期间到底(实际)发生了什么。加载类时是否生成代理类?方面库是否在 .class(编译时)文件中添加任何编程指令以生成代理类?

【问题讨论】:

    标签: java aop spring-aop


    【解决方案1】:

    Spring AOP 实际上将 Java 动态代理用于接口,如果需要,cglib 用于非接口类型。它仅适用于 Spring Bean。代理会自动为通过所谓的切入点匹配的所有方法生成。这是在接线过程中完成的。

    AspectJ 然而不需要甚至不使用代理,它直接生成字节码,将其编织到现有的字节码中。 AspectJ 更强大,可以做的不仅仅是方法拦截。

    • 对于编译时编织 (CTW),这是由 AspectJ 编译器 ajc 完成的。除了原生 AspectJ 语法(它是 Java 的超集),您还可以使用 Java 注释风格的方式来定义方面,通常称为 @AspectJ 语法。在这种情况下,您可以使用 javac 编译切面,并在单独的构建步骤中使用切面编织器。结果基本相同。在这两种情况下,在运行时,您都需要一个小型 AspectJ 运行时库,以使方面按预期工作。
    • CTW 和 LTW(加载时编织)之间的区别在于编织步骤被推迟到类加载时间。为了完成这项工作,您需要一个在 JVM 命令行上称为 AspectJ weaver 的 Java 代理库。 Java 代理在加载普通应用程序类之前启动,因此可以影响类加载并根据需要检测加载的字节码。分析工具或类似工具也使用此方法。
    • 显然,LTW 不适用于源代码,而是类文件,即 AspectJ 可以将其方面代码编织到任何常规 Java 类文件中。这也可以在运行时之前完成,即您可以将方面代码编织到您没有源代码的外部库中,创建一个新的修改版本,以便在每次加载库时为 LTW 节省时间.这通常称为二元编织。有了一些额外的知识,甚至可以将方面代码编织到 JDK 中,即通过创建一个包含方面代码的修改后的 rt.jar。但这不是您通常会做的事情,我只是想提一下这是可能的。

    【讨论】:

      【解决方案2】:

      不一定在编译时。在 Java 中,通过反射和类加载器,您可以在运行时以编程方式查看甚至修改创建方法和类。

      例如, "hello".getClass().getMethod("substring", Integer.TYPE).invoke("my sharona", 3) 将返回“sharona”,从 String 实例中提取方法子字符串并将其应用于另一个对象。

      使用自定义classloader,您可以定义如何从系统加载您的类。这样,您可以定义一个方法,该方法将调用以加载(或生成!)类的字节码。您还可以使用系统类加载器来加载类的字节码并检查它。

      这种技术被 Mozilla Rhino 广泛使用,它可以使用它将编译的 JavaScript 作为 Java 字节码加载以提高效率,或者 JavAssist,它允许您在运行时创建类、方法、字段和任何东西。

      JBoss 或 TomCat 等应用服务器也使用反射来检查和操作代码,尤其是通过注释。

      【讨论】:

      • 对类加载时间编织有了一个不错的想法。但是运行时呢?我不确定我在这里缺少什么......我在一些 xml 文件中有与方面相关的配置(不是通过注释)。加载类后,将创建对象并完成对象的链接(依赖)。现在你如何在类之间安装代理类。例如,一个 servlet 调用一项服务。现在记录器是通过 xml 文件建议的一个方面。现在如何让 JVM 在运行时知道这些?
      • 通过类加载器进行反射和类加载都在运行时工作,在这种情况下,通过在添加服务时将必要的字节码附加到方法中。是服务器还是库代码,它使用反射来查找方法来操作并在运行时更改它们。
      【解决方案3】:

      不确定什么是运行时编织。在加载时编织中,代理拦截类加载并在将字节码传递给类加载器之前对其进行修改。

      查看其工作原理非常简单,例如使用AspectJ。您可以使用编译时编织和反汇编代码来查看它是如何工作的。还可以指示 AspectJ 在加载时编织期间将生成的类保存在磁盘上。

      【讨论】:

      • 运行时和加载时的织法不一样吗??
      猜你喜欢
      • 2013-06-23
      • 2018-06-27
      • 1970-01-01
      • 2011-09-10
      • 2015-09-18
      • 1970-01-01
      • 1970-01-01
      • 2011-11-06
      • 1970-01-01
      相关资源
      最近更新 更多