在运行时编织方面

时间:2013-06-26 14:52:28

标签: java runtime aop aspectj load-time-weaving

我正在寻找一种Java解决方案,它允许我在运行时使用AOP在已经运行的代码之上编写新代码。关键是不要求重启JVM。另外,我想在运行时删除编织,让旧代码以编织前的方式运行。

我认为AspectJ加载时间编织+运行时类加载/卸载会做到这一点。有人试过吗?有什么建议? 谢谢。

3 个答案:

答案 0 :(得分:10)

需要考虑的一些事项:

  • 是的,您可以在类加载期间执行LTW ,但类已经加载后
  • 没有类卸载这样的概念,因为要卸载的类需要进行垃圾收集,因此不再存在对类的引用。即使后者是这种情况,JVM规范AFAIK也会将其声明为可选,无论是否卸载或GC应该清除已经加载的类。你永远不能依赖它。

话虽如此,您可以尝试OSGi之类的概念,也可以编写自己的类加载器(或者在Internet上找到许多现有的类加载器之一),它们将每个类或每个JAR加载到单独的类加载器实例中。这可能会变得任意复杂,所以也许你想要考虑这个简单的方法,只要它在你的情况的技术范围内:

  • 将您的方面编译到代码中或使用LTW,这并不重要。只需确保在实际使用类之前编写方面代码。编译时间显然已经足够快,加载时间刚好不够快,但很好。
  • 使用if() pointcuts获取所有相关建议,并提供动态更改切入点使用的变量值的方法,以便能够动态切换建议的开启和关闭。性能开销通常很小,不用担心。在你说它太昂贵之前试一试。

此解决方案满足您的条件,即可以(de)动态激活,并且在编制方面代码后不需要重新启动JVM。

答案 1 :(得分:7)

<强>方面

一个方面是您正在实施的跨领域功能。 这是您正在模块化的应用程序的方面或区域。一个方面最常见的(尽管很简单)示例是日志记录。记录是整个应用程序所需的。但是,由于应用程序倾向于根据功能分解为多个层,因此通过继承重用日志记录模块

没有意义。但是,您可以使用AOP创建日志记录方面并将其应用于整个应用程序。


<强>织

编织是将方面应用于目标对象以创建新的代理对象的过程。 这些方面被编织到指定连接点的目标对象中。编织可以在目标类的生命周期中的几个点进行:

  • 编译时间:在编译目标类时编入方面。这需要一个特殊的编译器。
  • 类加载时间:将目标类加载到JVM中时会编入方面。这需要一个特殊的ClassLoader 在引入类之前增强目标类的字节码 进入申请表。
  • 运行时:在应用程序执行期间的某些时间编织方面。通常,AOP容器将动态 生成一个代理类,该代理类将委托给目标类 编织方面。

enter image description here
enter image description here

(Source)

答案 2 :(得分:0)

您可以实施ASM解决方案,该解决方案允许在运行时(没有停机时间)在已经运行的代码之上织入新代码

  • ASM可以重新转换已加载的类,它基本上是读取文件上的类并在内存中重新转换已加载的类
  • 使用ASM(https://www.baeldung.com/java-asm)进行操作

您可以使用相同的解决方案在运行时除去机织物

  • 已加载的类保留在可以重新加载的文件系统上。