在@Transactional方法调用期间,初始化期间Bean属性不为null变为null
我遇到了一个问题,在调用@Transactional
方法期间bean的属性变为null。
-
UserService
是在@Configuration
类中声明的一个bean -
userRepository
和passwordService
在初始化期间是非空的(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'