【问题标题】:EnableLoadTimeWeaving annotation causes application context to fail to loadEnableLoadTimeWeaving 注解导致应用程序上下文加载失败
【发布时间】:2022-02-03 22:00:20
【问题描述】:

我正在尝试在 Spring Boot 应用程序中启用 AspectJ 加载时编织(不是 Spring AOP)。我的目标是在加载时将建议编织到带注释的字段和java.lang.reflect.Field.set(Object, Object)

根据Spring docs,我试过了:

@Configuration
@EnableLoadTimeWeaving
public class Config {}

使用此配置运行 Spring Boot 应用程序导致应用程序上下文无法加载并显示此消息:

Caused by: java.lang.IllegalStateException:
  ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader]
    does NOT provide an 'addTransformer(ClassFileTransformer)' method.
    Specify a custom LoadTimeWeaver or start your Java virtual machine
    with Spring's agent: -javaagent:spring-instrument-{version}.jar

该消息中的后一个建议不是一个好的选择,因为我试图避免需要修改启动脚本。我需要编织的方面实际上驻留在一个库中,因此所有实现 Spring Boot 的项目都必须做出使 LTW 工作所需的任何更改。

我也试过这个配置:

@Configuration
@EnableLoadTimeWeaving
public class Config implements LoadTimeWeavingConfigurer {

    @Override
    public LoadTimeWeaver getLoadTimeWeaver() {
        return new ReflectiveLoadTimeWeaver();
    }
}

使用此配置运行 Spring Boot 应用程序导致应用程序上下文无法加载并显示此消息:

Caused by: java.lang.IllegalStateException:
  ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader]
    does NOT provide an 'addTransformer(ClassFileTransformer)' method.

看来我需要让 JVM 使用具有addTransformer(ClassFileTransformer) 方法的类加载器。我不知道该怎么做,尤其是在这种情况下。有什么建议吗?

【问题讨论】:

  • 我想知道为什么这么多人拒绝修改启动脚本,而宁愿为像激活 Java 代理这样简单的事情更改编译的代码。热连接代理是可能的,但更具侵入性。此外,热附加的代理因此只能检测在附加代理之后加载的类,这使得这种设置有点脆弱。这有意义吗?
  • 是的,这很有意义。我没有意识到,所谓的热附加代理会比在启动脚本中指定代理更具侵入性和脆弱性。谢谢你的澄清,kriegaex。
  • 感谢您对我的一般性评论作出反应。我对你问题的实际回答呢?您是否至少验证过它是否适合您。你既没有接受也没有评论它。提前致谢。
  • 我很抱歉。我需要一些时间来复习你的答案。这是一个工作项目,所以我周末没有工作。

标签: spring spring-boot classloader aspectj load-time-weaving


【解决方案1】:

我不是活跃的 Spring 用户,但我知道 Spring 支持注解或 XML 配置的代理热附加,并且根据其 documentation 有一些特定于容器的类。不过,它似乎并非在所有情况下都能可靠地工作,尤其是在从 IDE 运行 Spring Boot 应用程序时。

无论如何,AspectJ weaver 1.8.7 and more recent can be hot-attached。我在 Spring 设置 here 中解释了如何做到这一点。如果您想要一个更简单的解决方案,它的样板更少,但更多地依赖于一个名为byte-buddy-agent 的小型帮助库,您可以使用this solution 作为快捷方式。我还没有尝试过,但我知道帮助程序库,并且在热附加字节码检测代理时自己在其他上下文中使用它,避免为迎合不同的 JVM 版本和配置情况而大惊小怪。但是为了让它在 JVM 9+ 上运行,您可能需要手动激活 JVM 的自动附加功能,这将是您启动脚本的另一项修改,您将回到第 1 步。

【讨论】:

  • 感谢您的回答。我同意您对我的帖子的评论,即通过启动脚本激活 Java 代理比代理热连接更可取。我还没有追求热附加代理,所以我不知道它是否适合我。然而,我走了一个不同的方向。我发现后编译编织将适用于大多数用例,而不是 LTW。对于边缘情况,用户可以通过启动脚本指定 Java 代理来实现 LTW。再次感谢你的帮助。您将我推向了更好的解决方案。
猜你喜欢
  • 1970-01-01
  • 2018-07-11
  • 2021-09-13
  • 2019-02-15
  • 1970-01-01
  • 2019-04-30
  • 1970-01-01
  • 2011-04-20
  • 1970-01-01
相关资源
最近更新 更多