【问题标题】:Bean properties not null during initialization become null during @Transactional method invocation初始化期间不为空的 Bean 属性在 @Transactional 方法调用期间变为空
【发布时间】:2017-07-24 16:25:04
【问题描述】:

我遇到了一个问题,即在调用 @Transactional 方法期间 bean 的属性变为空。

  • UserService 是在 @Configuration 类中声明的 bean
  • userRepositorypasswordService 在初始化期间不为空 (afterPropertiesSet)
  • 在调用 registerUser(即@Transactional)期间,这些属性变为空
  • 这些属性具有不可为空的类型
  • 已根据打印使用了相同的 UserService 实例/bean
  • 删除 @Transactional 似乎可以解决问题
  • 添加或删除@EnableTransactionManagement 似乎无济于事

服务:

open class UserService (val userRepository: UserRepository,
                        val passwordService: PasswordService) : InitializingBean {

    override fun afterPropertiesSet() {
        println("### this.afterPropertiesSet")
        println("### this: " + this)
        println("### userRepository: " + userRepository)
        println("### passwordService: " + passwordService)
    }

    @Transactional
    fun registerUser(request: UserRegistrationRequest): User {
        println("### this.registerUser")
        println("### this: " + this)
        println("### userRepository: " + userRepository)
        println("### passwordService: " + passwordService)
        val savedUser = this.userRepository.save(request.toUser())
        this.passwordService.savePassword(savedUser, request.password)
        return savedUser
    }

    private fun UserRegistrationRequest.toUser(): User { ... }

}

控制器:

@Controller
class UserController (val userService: UserService) : InitializingBean {
    override fun afterPropertiesSet() {
        println("### controller.afterPropertiesSet: " + userService)
        println("### user service: " + userService)
    }

    @PostMapping("/users")
    fun registerUser(@RequestBody userDetails: UserDetailsDto): ResponseEntity<UserDto> {
        println("### controller.registerUser: " + userService)
        println("### user service: " + userService)
        val registeredUser = userService.registerUser(userDetails.toUserRegistrationRequest())
        return ResponseEntity.ok(registeredUser.toDto())
    }

    private fun UserDetailsDto.toUserRegistrationRequest(): UserRegistrationRequest { ... }

    private fun User.toDto(): UserDto { ... }
}

Bean 声明:

@Configuration
@EnableTransactionManagement
open class ApplicationServicesConfiguration {

    @Bean
    open fun userService(userRepository: UserRepository,
                         passwordService: PasswordService): UserService = UserService(userRepository, passwordService)

    @Bean
    open fun passwordService(passwordRepository: PasswordRepository): PasswordService = PasswordService(passwordRepository)

}

打印:

### this.afterPropertiesSet
### this: com.sample.mojo.user.UserService@1ab14636
### userRepository: org.springframework.data.jpa.repository.support.SimpleJpaRepository@1961d75a
### passwordService: com.sample.mojo.user.PasswordService@36359723

### controller.afterPropertiesSet: com.sample.mojo.user.UserService@1ab14636
### user service: com.sample.mojo.user.UserService@1ab14636

### controller.registerUser: com.sample.mojo.user.UserService@1ab14636
### user service: com.sample.mojo.user.UserService@1ab14636

### this.registerUser
### this: com.sample.mojo.user.UserService@1ab14636
### userRepository: null
### passwordService: null

包结构

com.sample.app.Application
com.sample.app.ApplicationServicesConfiguration
com.sample.app.user.UserController
com.sample.app.user.UserService
com.sample.app.user.UserRepository
com.sample.app.user.PasswordService

这是 Spring 错误吗?还是 Kotlin-Spring 集成的怪癖?

【问题讨论】:

  • 你试过用UserService注释@Service吗?
  • 我没有。但是我在 @Configuration 类中将 UserService 声明为 @Bean。为了清楚起见,添加了 bean 声明。
  • @BranislavLazic 按要求添加了包结构
  • 对 Kotlin 不太熟悉,但 @Transactional fun 似乎是最终版本。这使其不可代理,因此它将使用代理的实例(null)而不是调用实际包装的实例。尝试制作函数open

标签: java spring spring-boot kotlin


【解决方案1】:

尝试将事务函数标记为打开。

有一个用于将所有类标记为打开的 gradle 插件:

buildscript{
    dependencies {
        classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
    }
}
apply plugin: 'kotlin-spring'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    相关资源
    最近更新 更多