【问题标题】:@Transactional proxyTargetClass and @Inherited@Transactional proxyTargetClass 和 @Inherited
【发布时间】:2019-03-27 23:16:49
【问题描述】:

关于@Transactional,我有 2 个问题无法为他们解答:

1- 界面上的@Transnational
根据答案:

如果您将应用设置为 proxy-target-class='true'(在您的应用上下文中,如果您对接口进行注释,则不会获取您的 @Transactional 信息。

我将 application.properties 配置为:

spring.aop.proxy-target-class=true

并且界面上的注释仍然被选中,我还尝试了以下方法(EnableTransacationManagement 上的proxyTargetClass = true):

@SpringBootApplication
@EnableAsync
@EnableTransactionManagement(proxyTargetClass = true)
public class Application extends SpringBootServletInitializer {
}

@Transnational 仍然在我只在 interface 上配置的地方工作,所以我在这里缺少什么?

2- @Transnational 有@Inherited,@inherited 根据 java 文档:

请注意,如果注释类型用于注释类以外的任何内容,则此元注释类型无效。另请注意,此元注释仅导致注释从超类继承;已实现接口上的注释无效。

我有以下用@Transnational 注释的接口,它仍在处理扩展它的接口:

@Repository
@Transactional
public interface UserRepository extends JpaRepository<User, Long> {


}

以下/下面的接口有修改查询,如果没有@Transactional,它将无法工作,我已经用@Transacational 注释了上面的接口并且它正在被拾取(如果我在父方法而不是类上配置它甚至可以工作):

public interface TestRepository extends UserRepository {

@Query("UPDATE User U set U.name='hello' where U.id=1")
@Modifying
public void test();

}

如果@Inherited 对接口没有影响,那么事务如何工作?


更新:问题 1

我什至在接口方法上尝试了@Async,它在没有注释实现类的情况下工作,AOP 正在使用 CGLIB 代理(仅在注释接口方法时)这与大多数不确定是否有问题的答案相矛盾。

【问题讨论】:

  • @Transactional@Async 工作是因为 Spring,在这些情况下,还会扫描由类实现的接口以查找该注释。这是 Spring 中的一个特性,与注解是否为 @Inherited 无关。虽然,恕我直言,您不应该将这些注释放在接口上,因为它们属于类。这些行为应该是实现细节。最后,您在引用常规 Spring 参考指南时使用了 Spring Data JPA。 Spring Data JPA 有另一种检测@Transactional 等的方法。
  • @M.Deinum 代理目标类呢?如果我们不使用JDK代理,接口上的注释不应该被忽略吗?如果注释只设置在接口方法上,那么为什么 CGLIB 不忽略它
  • 因为不管它是如何代理的,Spring会检测实现的接口,如果在实现类上找不到,就会扫描那些。
  • @M.Deinum 那么这里的第二个答案不正确?stackoverflow.com/questions/5551541/…)。 ?它有 40 票,上面写着 If you have your app set to proxy-target-class='true' (在您的应用程序上下文中,如果您对接口进行注释,则不会获取您的事务信息。
  • 该答案不适用于此处,因为您使用的是 Spring Data JPA……该答案适用于基于 Spring 的常规 bean 和 IIRC,其行为已更改,并且无论如何都会在接口上检测到该信息。跨度>

标签: java spring spring-boot transactional


【解决方案1】:

您链接到的答案是 Spring 3.0,但目前我们处于 Spring 5.1。这大约是 7 个版本,参考指南的那部分不再存在。

不管你使用哪种代理模式,当在实现上找不到时,Spring总是会尝试在实现接口上找到@Transactional注解。这是 Spring 的行为,在 Spring 中专门实现,这偏离了默认的注解继承规则。 (通常在执行getAnnotation 时这是行不通的,所以 Spring 实现了这个)。另请参阅 Spring 参考指南的 this section

除此之外,您还使用 Spring Data JPA,它还专门为其创建的动态存储库添加元数据和注释处理。

【讨论】:

    猜你喜欢
    • 2014-02-26
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    • 2015-09-27
    • 2016-07-24
    • 2017-11-08
    • 2023-03-10
    • 1970-01-01
    相关资源
    最近更新 更多