You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+MongoDB项目出现ObjectMapper转UserService类型转换异常求助

问题分析:Spring Boot中ObjectMapper转UserService的类型转换异常

错误日志

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userController'
    Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.pypek.testtaskapi.controller.UserController]: Constructor threw exception
        Caused by: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'com.fasterxml.jackson.databind.ObjectMapper@5f4d427e' with class 'com.fasterxml.jackson.databind.ObjectMapper' to class 'com.pypek.testtaskapi.service.UserService'
        ...(错误栈省略)

相关代码

UserController(Groovy)

package com.pypek.testtaskapi.controller

import com.pypek.testtaskapi.model.User
import com.pypek.testtaskapi.service.UserService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/user")
class UserController {

@Autowired
UserService service

UserController(UserService service) {
    this.service = service
}

@GetMapping("/{id}")
def getUser(@PathVariable String id) {
    return service.getUser(id)
}

@PatchMapping
def updateUser(@RequestBody User user){
    service.updateUser(user)
}

@PostMapping
def addUser(@RequestBody User user){
    service.addUser(user)
}

@DeleteMapping("/{id}")
def deleteUser(@PathVariable String id){
    service.deleteUser(id)
}
}

UserService(Groovy)

package com.pypek.testtaskapi.service

import com.pypek.testtaskapi.exceptions.UserNotFoundExceptions
import com.pypek.testtaskapi.model.User
import com.pypek.testtaskapi.repository.UserRepository
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service

@Service
class UserService {

    UserRepository repository

    @Autowired
    UserService(UserRepository repository) {
        this.repository = repository
    }

    def getUser(String id) {
        return repository.findById(id).orElseThrow(() -> new UserNotFoundExceptions(id))
    }

    String addUser(User user) {
        return repository.save(user).getId()
    }

    def updateUser(User user) {
        def id = user.getId()
        if (checkIfUserExist(id)){
            return repository.save(user)
        } else throw new UserNotFoundExceptions(id)
    }

    def deleteUser(String id) {
        if (checkIfUserExist(id)) {
            repository.deleteById(id)
        } else throw new UserNotFoundExceptions(id)
    }

    def checkIfUserExist(String id) {
        return repository.existsById(id)
    }
}

问题原因

你在UserController中同时使用了字段注入(@Autowired标注在service字段上)和构造函数注入(手动编写接收UserService参数的构造函数),在Groovy环境下,Spring的依赖注入解析逻辑出现混淆:

  • 当类存在自定义构造函数时,Spring会优先尝试构造函数注入;
  • 但字段上的@Autowired注解干扰了Spring的依赖匹配逻辑,导致Spring错误地将上下文存在的ObjectMapper Bean尝试注入到构造函数中,最终引发类型转换异常。

解决方法

只需保留一种注入方式即可,推荐使用构造函数注入(更符合依赖注入最佳实践,便于测试和依赖明确):

方案一:保留构造函数注入,移除字段上的@Autowired

修改后的UserController代码:

package com.pypek.testtaskapi.controller

import com.pypek.testtaskapi.model.User
import com.pypek.testtaskapi.service.UserService
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/user")
class UserController {

    final UserService service

    UserController(UserService service) {
        this.service = service
    }

    @GetMapping("/{id}")
    def getUser(@PathVariable String id) {
        return service.getUser(id)
    }

    @PatchMapping
    def updateUser(@RequestBody User user){
        service.updateUser(user)
    }

    @PostMapping
    def addUser(@RequestBody User user){
        service.addUser(user)
    }

    @DeleteMapping("/{id}")
    def deleteUser(@PathVariable String id){
        service.deleteUser(id)
    }
}

方案二:保留字段注入,移除自定义构造函数

修改后的UserController代码:

package com.pypek.testtaskapi.controller

import com.pypek.testtaskapi.model.User
import com.pypek.testtaskapi.service.UserService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/user")
class UserController {

    @Autowired
    UserService service

    @GetMapping("/{id}")
    def getUser(@PathVariable String id) {
        return service.getUser(id)
    }

    @PatchMapping
    def updateUser(@RequestBody User user){
        service.updateUser(user)
    }

    @PostMapping
    def addUser(@RequestBody User user){
        service.addUser(user)
    }

    @DeleteMapping("/{id}")
    def deleteUser(@PathVariable String id){
        service.deleteUser(id)
    }
}

内容的提问来源于stack exchange,提问作者Olexie Polishchyk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 13:06:02