![](/img/trans.png)
[英]Spring 3 : @Autowired dao fields are null in service beans with @Transactional annotation
[英]Spring @Transactional preventing @Autowired in @Service
我有一個帶有一堆@Autowired
服務的服務。 當我將其中一種方法更改為@Transactional
時,它阻止了所有@Autowired
,因為它們都是 null。
例子:
@Service
open class UserService {
@Autowired
private val userRepository : UserRepository? = null
@Autowired
private val emailService : EmailService? = null
@Transactional
@Throws(EmailConflictException::class)
open fun insert(newUser: User, context : RequestContext) {
if(!isEmailAvailable(newUser.email)) throw EmailConflictException()
val user = userRepository!!.insert(newUser, context.org.id)
emailService!!.send(userEmailFactory!!.getInviteEmail(user))
}
}
emailService 和 userRepository 在運行時調用 insert 時都是 null。 如果我從 insert 方法中刪除了@Transactional
,那么 emailService 和 userRepository 都是在運行時定義的。
為什么會這樣? 我如何解決它
此問題通常是由於項目中沒有plugin.spring
插件引起的。 這是因為 Kotlin 類和成員默認情況下是final
的,這與 Spring AOP(即代理數據庫事務)沖突。
plugin.spring
是kotlin-allopen
的包裝器,包括 Spring 注釋,如@Transactional
。
嘗試在您的項目中添加plugin.spring
。 例如; 工作配置如下所示。
plugins {
id("org.springframework.boot") version "2.4.2"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.4.21"
kotlin("plugin.spring") version "1.4.21"
}
這是文檔 - https://kotlinlang.org/docs/all-open-plugin.html#gradle
注意:問題顯示 class 和 function 是打開的。 理論上應該足夠了。 但是由於 OP 沒有顯示完整的項目設置以及如何調用此代碼。 不確定為什么open
的 function 沒有得到正確初始化的 bean。
我認為 Deinum 的想法是正確的。 為了增加一些風味,請閱讀 CgLib 與動態代理作為一個概念。
https://cliffmeyers.com/blog/2006/12/29/spring-aop-cglib-or-jdk-dynamic-proxies.html
作為一件便宜的事情,您也可以嘗試,盡管它可能感覺違反直覺,但嘗試將“setter”和“getter”添加到您的私有變量中。
然后,不要直接引用 userRepository.insert...,而是將其更改為使用 getUserRepository().insert...
通過這種方式,通過暴露 getter/setter,Spring 調用 setter 設置並返回 getter 更好地集中在同一個最終代理目標上,這樣你就可以訪問相同的私有變量,而不是直接訪問 dummy代理包裝器的未初始化變量。
讓我知道這是否有幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.