簡體   English   中英

Spring @Transactional 防止 @Autowired 在 @Service

[英]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.springkotlin-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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM