gpt4 book ai didi

Grails 的@Transactional 将禁用@CompileStatic 注释

转载 作者:行者123 更新时间:2023-12-02 14:31:11 25 4
gpt4 key购买 nike

我在服务方法上添加了两个注解,编译后发现方法被编译成一个新的类文件,我反编译生成的类文件,发现@CompileStatic 没有按预期工作。

是正确的还是 grails 的错误?

class FoobarService {
@grails.transaction.Transactional
@groovy.transform.CompileStatic
void foobar() {
....
}
}

最佳答案

grails.transaction.Transactional注释是传统 Spring org.springframework.transaction.annotation.Transactional 的替代品注解。它具有相同的属性和特性,工作原理基本相同,但它避免了使用 Spring 注释的不幸副作用。

Spring 注解触发了注解类的运行时代理的创建。 Spring 使用 CGLIB 创建目标类的子类(通常是 Grails 服务),并将 CGLIB 代理的实例注册为 Spring bean,而不是直接注册服务实例。代理获取您的服务实例作为数据变量。

每个方法调用都在代理中被拦截,它会根据事务设置进行所需的任何检查和/或设置,例如加入一个现有的事务,创建一个新的事务,抛出一个异常,因为一个还没有运行,等等。一旦完成,你的真实方法就会被调用。

但是,如果您调用具有不同设置的另一个带注释的方法(例如,第一个方法使用 @Transactional 中的默认设置,但第二个应该在新的单独事务中运行,因为它带有 @Transactional(propagation=REQUIRES_NEW) 注释),那么第二个注释设置将被忽略因为您在代理“下方”,在代理正在拦截调用的服务的真实实例中。但它不能拦截这样的直接调用。

传统的解决方法是避免直接调用,而是在代理上进行调用。您不能(至少不方便)将服务 bean 注入(inject)到自身中,但您可以访问应用程序上下文并以这种方式访问​​它。所以在那种情况下你需要的电话就像

ctx.getBean('myService').otherMethod()

这有效,但很丑陋。

不过,新的 Grails 注释的工作方式有所不同。它会在编译期间通过 AST 转换触发代码的重做。为每个带注释的方法创建第二个方法,并将真实方法的代码移到其中,在 GrailsTransactionTemplate 中使用注释设置运行代码。到达那里后,代码将使用所需的事务设置运行,但由于每个方法都以这种方式重写,因此您不必担心代理以及从哪里调用方法 - 没有代理。

不幸的是,您看到了一个副作用 - 显然转换发生的方式不会保留 @CompileStatic注释,因此代码以动态模式运行。对我来说听起来像是一个错误。

关于Grails 的@Transactional 将禁用@CompileStatic 注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29312070/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com