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

时间:2017-03-04 15:41:45

标签: java spring spring-boot kotlin

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

  • UserService是在@Configuration
  • 中声明的bean 初始化userRepository 期间,
  • passwordService(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 bug吗?还是Kotlin-Spring整合怪癖?

1 个答案:

答案 0 :(得分:0)

尝试将交易功能标记为已打开。

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

<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table class="table table-bordered table-stripped" id="TableOne" style="width: 100%">
  <thead>
    <tr>
      <th></th>
      <th colspan="2" style="text-align: center">AM</th>
      <th colspan="2" style="text-align: center">PM</th>
      <th></th>
    </tr>
    <tr>
      <th width="30%">Category</th>
      <th width="15%">Weekday</th>
      <th width="15%">Weekend</th>
      <th width="15%">Weekday</th>
      <th width="15%">Weekend</th>
      <th width="10%"></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <select class="form-control BundleAssetType" autocomplete="off" name="asset_category_id[]">
          <option value="">--Select Category --</option>
          <option value="4">Medium Roller</option>
          <option value="2">Paver</option>
          <option value="1">Small Roller</option>
          <option value="3">Sweet Paver</option>
        </select>

      </td>
      <td>
        <input type="text" autocomplete="off" name="weekday_am[]" class="form-control WeekdayAssetAm">
      </td>
      <td>
        <input type="text" autocomplete="off" name="weekend_am[]" class="form-control WeekendAssetAm">
      </td>
      <td>
        <input type="text" autocomplete="off" name="weekday_pm[]" class="form-control WeekdayAssetPm">
      </td>
      <td>
        <input type="text" autocomplete="off" name="weekend_pm[]" class="form-control WeekendAssetPm">
      </td>
      <td>
        <div class="btn-group btn-group-sm" role="group" aria-label="">
          <button type="button" class="add btn btn-sm btn-primary">+</button>
          <button type="button" class="deleteB btn btn-sm btn-danger">-</button>
        </div>
      </td>
    </tr>
  </tbody>
</table>