在@Transactional方法调用期间,初始化期间Bean属性不为null变为null

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

  • UserService是在@Configuration类中声明的一个bean
  • userRepositorypasswordService在初始化期间是非空的(afterPropertiesSet)
  • 在调用registerUser( @Transactional )期间,这些属性将变为null
  • 这些属性具有不可空的types
  • 用户服务的相同实例/ 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 { 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的bug? 还是Kotlin-Spring整合的怪癖?

尝试将交易function标记为打开。

有一个gradle插件可以将所有的类标记为open:

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