2

因为 Spring 驱动的 AspectJ LTW 无法编织在 Spring 初始化之前加载的类,所以我将 Spring 项目转换为纯 Aspectj LTW(使用 AspectJ weaver java 代理)。

但是,这同时在我们的单元测试中启用了 AOP,因为我需要将 AspectJ 的代理添加到 Maven Surefire 插件 argLine 参数以及我团队的 IDE (IntelliJ IDEA) 中的默认 TestNG 配置。

如果我们的 Aspects 不依赖于 Spring,这不会成为问题,但是其中一些实际上需要通过 @Resource 表示法将 Spring bean 注入到它们的字段中。由于在单元测试期间未启动 Spring,因此该字段将为 null 并导致 NullPointerExceptions。

尽管我可以在构建过程中配置 Surefire 插件的两个独立执行:一个有代理,另一个没有它;这个解决方案将变得不切实际,因为每个开发人员仍然需要更改 IDE 的单元测试测试配置,而不是实际需要 AOP 和启动 Spring 的其他测试,对于每个独立的测试执行(即在 Maven 构建过程之外)。

为了解决这个问题,最好的方法是什么?有什么方法可以禁用 AspectJ 的 LTW,同时仍然保持 Java 代理配置不变?或者也许是另一种更灵活的方式来配置不存在 Spring 驱动的 AspectJ LTW 问题的 AspectJ 的 LTW?

4

1 回答 1

3

我们可以争论使纯 AspectJ 方面依赖于 Spring 魔法是否是一个好的设计决策,或者是否可以选择将 Spring bean 的模型注入到方面。实际上,如果需要这样的框架,单元测试就不是单元测试。可以说,方面也是如此。

无论如何,这是一个便宜的解决方案:对所有相关建议使用if()切入点,并使它们取决于您是否处于测试模式。性能开销通常很小,不用担心。在你说它太贵之前先试一试。

cflow()也可以通过或确定测试类是否在当前截获的连接点的控制流中,但成本更高cflowbelow()。不过在这种情况下我不推荐它。

第三种选择可能是将另一个META-INF/aop.xml添加到测试模式下的类路径中,其中包含一个全局排除语句,将所有类排除在编织之外。AspectJ 文档解释了多个aop.xml如何在逻辑上合并。可能这个选项是最好的,因为它不需要你改变你的方面。我没试过,但如果你遇到任何困难,我会给我一个标志。

于 2013-07-13T18:28:40.677 回答