【问题标题】:How to use jpa:repositories with proxy-target-class="true"如何使用 jpa:repositories 和 proxy-target-class="true"
【发布时间】:2012-12-20 17:05:19
【问题描述】:

我用

<tx:annotation-driven transaction-manager="transactionManager" />
<jpa:repositories base-package="com.xxwell.amkey.domain"
    transaction-manager-ref="transactionManager" />

它就像一个魅力。但是,要向项目添加方面,我需要 CGLIB。将上述行更改为

<tx:annotation-driven transaction-manager="transactionManager"
    proxy-target-class="true" />
<jpa:repositories base-package="com.xxwell.amkey.domain"
    transaction-manager-ref="transactionManager" />

导致启动上下文失败:Cannot subclass final class class $Proxy45 对于我定义的每个存储库。是不能一起用,还是可以做?

【问题讨论】:

  • 我知道这是一个老问题,但是如果您需要 cglib 样式代理,那么您必须从存储库接口中删除 @Transactional 注释,并将其移动到 service/s 类/叫它的人。
  • @Luciano,我还没有来测试这个,但无论如何:请把它写成答案,所以我可以接受它。

标签: spring spring-aop spring-data


【解决方案1】:

如果您需要 cglib 样式代理,则必须从存储库接口中删除 @Transactional 注释,并将其移至调用它的服务/s 类/es。

CGLIB 样式扩充直接作用于它扩充的类。接口无关紧要。

【讨论】:

  • 我很想真正理解为什么会这样,但你是对的。文档似乎没有提到这一点。
  • @MPi JDK 代理使用接口。如果你的类 A 实现了 B,那么它会构建一个也实现 B 的代理 B',并包装 A。所以你仍然看到 B,当它调用函数 f() 时,方面发生在函数 A.f 之前(或之后) ()。为了让代理知道要包装什么,注释必须对接口方法进行注释,因为它并不真正关心 A,只要它实现 B。另一方面,CGLIB 增强了类 A。它不关心它实现了哪些接口。因此,要让它知道要增强什么,注释必须位于 A 类中。
【解决方案2】:

final 方法不能被建议,因为它们不能被覆盖。也许您的父类之一具有最终方法,或者您的类是最终的。

【讨论】:

  • 确实如此。但是,失败消息是针对我的 Spring Data 存储库的,它们是接口(所以没有什么是最终的)。
【解决方案3】:

其他选项是摆脱

proxy-target-class="true"

通过在所有 AOP 位置引入适当的接口(假设在服务层)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-31
    • 2015-08-06
    • 2023-03-12
    相关资源
    最近更新 更多