Spring 5.0 MVC自定义Role反序列化器依赖注入异常求助
解决Spring MVC中自定义Jackson反序列化器无法注入EntityManager的问题
我之前也踩过完全一样的坑,核心矛盾在于Jackson默认会自行实例化反序列化器,完全不感知Spring的上下文,所以不管是用带EntityManager的构造函数,还是用@PersistenceContext字段注入,都会出问题。下面是我亲测有效的解决方案:
步骤1:将反序列化器声明为Spring管理的Bean
先把你的RoleDeserializer改成Spring组件,并且用构造函数注入EntityManager(这是Spring官方推荐的注入方式,比字段注入更可靠、更易测试):
@Component public class RoleDeserializer extends JsonDeserializer<Role> { private final EntityManager em; // 让Spring自动将EntityManager装配到构造函数中 public RoleDeserializer(@PersistenceContext EntityManager em) { this.em = em; } @Override public Role deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { // 这里编写你的反序列化逻辑,比如从JSON读取ID后查询数据库 String roleId = jsonParser.getText(); return em.find(Role.class, roleId); } }
步骤2:配置Jackson使用Spring管理的反序列化器
接下来要告诉Spring MVC的Jackson消息转换器,使用我们注册的Spring Bean作为Role类型的反序列化器,而不是让Jackson自己去实例化。
在你的Spring MVC配置类(带有@Configuration和@EnableWebMvc注解的类)中添加如下配置:
@Configuration @EnableWebMvc public class WebMvcConfig implements WebMvcConfigurer { private final RoleDeserializer roleDeserializer; // 构造函数注入我们的反序列化器Bean public WebMvcConfig(RoleDeserializer roleDeserializer) { this.roleDeserializer = roleDeserializer; } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 构建ObjectMapper并注册自定义反序列化器 Jackson2ObjectMapperBuilder mapperBuilder = new Jackson2ObjectMapperBuilder(); mapperBuilder.deserializerByType(Role.class, roleDeserializer); // 将配置好的ObjectMapper注入到消息转换器中 converters.add(new MappingJackson2HttpMessageConverter(mapperBuilder.build())); } }
步骤3:移除实体类上的@JsonDeserialize注解(可选但推荐)
因为我们已经通过全局配置为Role类型指定了反序列化器,所以可以把实体类上的@JsonDeserialize(using = RoleDeserializer.class)去掉,避免重复配置导致混淆。
为什么之前的方法行不通?
- 直接用
@JsonDeserialize(using = ...)时:Jackson会尝试自行创建RoleDeserializer实例,它完全不了解Spring的依赖注入机制,因此必须要有无参构造函数,而你的构造函数依赖EntityManager,所以抛出无默认构造的异常。 - 用
@PersistenceContext字段注入时:Jackson创建的RoleDeserializer实例不在Spring的上下文管理范围内,Spring不会为这个实例执行依赖注入,因此em始终是null。
内容的提问来源于stack exchange,提问作者LeO
相关产品推荐
相关产品推荐

