Spring Boot中如何在Jackson自定义序列化器中注入CRUD服务?
Spring Boot中如何在Jackson自定义序列化器中注入CRUD服务?
嗨,我完全能理解你碰到的这个问题——Jackson的序列化器默认是自己实例化的,不受Spring管理,所以直接用@Autowired或者手动拿上下文经常会出现空指针,我来给你捋捋怎么解决。
首先,你之前尝试的@Component和ApplicationContext相关的方法之所以没成功,核心原因是:Jackson默认会自己new一个你的序列化器实例,这个实例根本不是Spring托管的,所以Spring没法给它注入服务。
下面给你两种靠谱的解决方案,优先推荐第一种,更简洁:
方案一:用@JsonComponent注解(Spring Boot专属)
这个注解是Spring Boot专门为Jackson序列化/反序列化组件设计的,它会自动把你的序列化器注册到Spring的ObjectMapper里,同时让Spring托管这个类的实例,这样注入服务就没问题了。
修改你的代码如下:
@JsonComponent // 替换掉原来的@Component,这个注解自带Spring托管和Jackson注册功能 public class Template1Serializer extends JsonSerializer<Template1> { private final CustomerUserServiceIMPL customerUserServiceIMPL; // 用构造器注入服务,Spring会自动把实例传进来,完全不需要手动拿上下文 public Template1Serializer(CustomerUserServiceIMPL customerUserServiceIMPL) { this.customerUserServiceIMPL = customerUserServiceIMPL; } @Override public void serialize(Template1 template1, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { String usuarioContent = ""; try { String userInfo = getuser(); usuarioContent = userInfo != null ? userInfo : "no hay nada"; } catch (Exception e) { usuarioContent = "Error al obtener información del usuario"; e.printStackTrace(); } jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("body", template1.getTemplateText() + " - Mensaje añadido serializador" + usuarioContent + "final"); jsonGenerator.writeEndObject(); } private String getuser() { System.out.println("Servicio ejecutado"); Optional<valueContacts> profiletest = customerUserServiceIMPL.getCustomerFromPhonenunmber("573248324121"); if (profiletest.isPresent()) { valueContacts profile = profiletest.get(); System.out.println(profile.getCustomerName()); System.out.println(profile.getCedula()); return "hola querido usuario tu nombre es " + profile.getCustomerName() + " y tu cedula es " + profile.getCedula(); } else { System.out.println("No se encontró el perfil."); return null; } } }
为什么这个能行?
@JsonComponent会让Spring创建并管理这个序列化器的实例,同时自动把它注册到Jackson的ObjectMapper中,这样Jackson在序列化Template1的时候,用的就是Spring托管的那个实例,构造器里注入的服务自然就有值了。- 构造器注入是Spring推荐的方式,能保证实例创建的时候服务已经被注入,避免了
@PostConstruct那种后续初始化的麻烦,也不会有空指针。
方案二:手动配置Jackson注册Spring托管的序列化器
如果你不想用@JsonComponent,也可以手动配置Jackson来使用Spring托管的序列化器:
- 保留你的序列化器上的
@Component注解:
@Component public class Template1Serializer extends JsonSerializer<Template1> { private final CustomerUserServiceIMPL customerUserServiceIMPL; // 构造器注入 public Template1Serializer(CustomerUserServiceIMPL customerUserServiceIMPL) { this.customerUserServiceIMPL = customerUserServiceIMPL; } // 后面的serialize和getuser方法和上面一致 }
- 创建一个Jackson配置类,把序列化器注册到ObjectMapper:
@Configuration public class JacksonConfig { private final Template1Serializer template1Serializer; // 注入Spring托管的序列化器实例 public JacksonConfig(Template1Serializer template1Serializer) { this.template1Serializer = template1Serializer; } @Bean public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() { // 告诉Jackson,序列化Template1类型的时候用我们的托管序列化器 return builder -> builder.serializerByType(Template1.class, template1Serializer); } }
额外注意事项
- 确保你的
CustomerUserServiceIMPL类上已经加了@Service或者@Component注解,让Spring能托管它,否则没法注入。 - 尽量避免用字段注入(
@Autowired直接加在字段上),构造器注入更安全,也更容易测试。
这样修改后,你的序列化器里就能正常使用CRUD服务了,不会再出现null的情况~
备注:内容来源于stack exchange,提问作者juancamilo ariasotalvaro
相关产品推荐
相关产品推荐

