为什么spring @transactional对appectj不可靠?

发布于 2025-01-20 22:44:16 字数 1253 浏览 4 评论 0原文

TLDR:该项目重现了该问题: https://github.com/moreginger/aspectj-no- tx

编辑:上面现在无需 jooq 即使用普通 JDBC 进行复制。

编辑:Spring bug - https://github.com/spring-projects/spring -framework/issues/28368


我一直在尝试使用 AspectJ 为 Kotlin 代码库编织 Spring @Transactional。我已经看到它可以在加载时和编译时编织中使用(后者使用 io.freefair.aspectj.post-compile-weaving )。然而,当我编写一个测试,在异常后事务将被取消时,发生了一些奇怪的事情:测试有时会失败。事实证明,它在第一次测试套件运行时总是失败,然后第二次将首先运行(由于第一次失败)并通过。经过大量调查,我的代码库中的“最小”情况是(在同一套件中运行):

  • 运行一个测试,该测试调用 上标记为 @Transactional 的方法@Autowired bean。
  • 在不同的类中运行测试,该测试调用不同 @Autowired bean 上标记为 @Transactional 的另一个方法,该方法将进行一些更改,然后抛出异常一个例外。断言所做的更改不可见。这失败了。

然后,如果您再次运行该套件,由于第一次失败,它会首先运行第二次测试并通过。它继续按此顺序运行并传递,直到出现其他问题或运行 gradle clean 为止。 (请注意,为了避免顺序交换,您可以使第一个测试也失败)。

无论我使用加载时编织还是编译时编织,都会发生同样的事情。

怎么会这样呢?特别是在编译时编织时,事务已合并到类文件中。访问不同的 @Transactional 方法如何导致我们稍后访问的方法不再是 @Transactional o_O ?我已经验证,只需从第一个“修复”问题中删除 @Transactional 即可。

TLDR: this project reproduces the issue: https://github.com/moreginger/aspectj-no-tx

Edit: Above now reproduced without jooq i.e. using plain JDBC.

Edit: Spring bug - https://github.com/spring-projects/spring-framework/issues/28368


I've been trying to use AspectJ to weave Spring @Transactional for a Kotlin codebase. I've seen it working with both load-time and compile-time weaving (the latter using io.freefair.aspectj.post-compile-weaving). However, when I wrote a test that the transaction would be unwound after an exception something strange happened: the test would sometimes fail. It turned out that it always failed on the first test suite run, then the second time around it would run first (due to failing the first time) and pass. After much investigation, a "minimal" case in my codebase is (in the same suite run):

  • Runs a test which calls a method marked @Transactional on an @Autowired bean.
  • Runs a test in a different class that calls another method marked @Transactional on a different @Autowired bean, which will make some changes and then throw an exception. Assert that the changes made aren't visible. This fails.

Then if you run this suite again it runs the second test first due to failing the first time and passes. It continues to run in this order and pass until something else fails or gradle clean is run. (Note that to avoid the order swapping you can make the first test also fail).

The same thing happens whether I use load-time or compile-time weaving.

How can this be? Especially with compile-time weaving the transactions have been incorporated into the class files. How can accessing a different @Transactional method cause one that we access later to stop being @Transactional o_O ? I've verified that simply removing @Transactional from the first "fixes" the issue.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文