我遇到了一篇关于 AOP 的文章,其中提到 Aspect weaving 可以在编译时、类加载时和运行时发生。
在 java 中,我可以想象,相当理解,方面编织在编译期间实际上是如何发生的。代理类是在类编译期间生成的(在项目上启用方面)。生成的字节码将具有代理代码。
但我仍然想知道在类加载时间编织和运行时编织期间究竟(实际上)发生了什么。加载类时是否生成代理类?方面库是否在 .class(编译时)文件中添加任何编程指令以生成代理类?
我遇到了一篇关于 AOP 的文章,其中提到 Aspect weaving 可以在编译时、类加载时和运行时发生。
在 java 中,我可以想象,相当理解,方面编织在编译期间实际上是如何发生的。代理类是在类编译期间生成的(在项目上启用方面)。生成的字节码将具有代理代码。
但我仍然想知道在类加载时间编织和运行时编织期间究竟(实际上)发生了什么。加载类时是否生成代理类?方面库是否在 .class(编译时)文件中添加任何编程指令以生成代理类?
Spring AOP实际上对接口使用 Java 动态代理,如果需要,对非接口类型使用cglib 。它仅适用于 Spring Bean。代理会自动为通过所谓的切入点匹配的所有方法生成。这是在接线期间完成的。
然而, AspectJ不需要甚至不使用代理,它直接生成字节码,该字节码被编织到现有的字节码中。AspectJ 功能更强大,可以做的不仅仅是方法拦截。
不一定在编译时。在 Java 中,通过反射和类加载器,您可以在运行时以编程方式查看甚至修改创建方法和类。
例如,
"hello".getClass().getMethod("substring", Integer.TYPE).invoke("my sharona", 3)
将返回“sharona”,从 String 实例中提取方法子字符串并将其应用于另一个对象。
使用自定义类加载器,您可以定义如何从系统加载您的类。这样,您可以定义一个方法,该方法将调用以加载(或生成!)类的字节码。您还可以使用系统类加载器来加载类的字节码并检查它。
这种技术被 Mozilla Rhino 广泛使用,它可以使用它将编译的 JavaScript 作为 Java 字节码加载以提高效率,或者JavaAssist,它允许您在运行时创建类、方法、字段和任何东西。
JBoss 或 TomCat 等应用服务器也使用反射来检查和操作代码,尤其是通过注释。
不确定什么是运行时编织。在加载时编织中,代理拦截类加载并在将字节码传递给类加载器之前对其进行修改。
看看它是如何工作的很容易,例如使用AspectJ。您可以使用编译时编织和反汇编代码来查看它是如何工作的。还可以指示 AspectJ 在加载时编织期间将生成的类保存在磁盘上。