Spring Boot 2.x Jackson ObjectMapper实例未注入服务类-尝试从配置类引导默认&使用bean方法

问题描述

我看到在Spring Boot 2.3.4.RELEASE中注入Jackson ObjectMapper时出现了怪异的行为。

我的maven依赖项中同时包含spring-boot-starter-webspring-boot-starter-json。但是,当我在ObjectMapper类之一中自动连线@Service时,它不会被注入并且引用为空。

然后,我尝试在@Primary类的@Bean @Configuration bean方法中手动创建并返回一个,但结果仍然相同。

我知道@Configuration可以正常工作,因为其中的其他bean方法用于正确注入其他对象。另外,我还在bean方法添加了一条log语句,该语句返回ObjectMapper实例,该实例也正在被记录,但是@Service类上的引用仍然为null? (我也曾尝试白白添加@AutoConfigureAfter(JacksonAutoConfiguration.class)

还有其他人遇到这个问题或知道这里发生了什么吗?请扔光。

谢谢

编辑(10/22):以下是@Service类的摘要

@Lazy
@Service
@EnableSpringConfigured
public class SampleServiceSingletonService {

  private static final Logger LOGGER = LoggerFactory.getLogger(SampleServiceSingletonService.class);

  @Autowired
  protected ThreadPoolTaskScheduler threadPoolTaskScheduler;
  
  @Autowired
  private ObjectMapper objectMapper;
  
  @EventListener({ApplicationReadyEvent.class})
  private void initOnAppReady() {
      LOGGER.info("No need to create ObjectMapper instances,most customizations can be set/overriden in application.properties,look at the one here for reference");
      LOGGER.info("Injected ObjectMapper: {}",objectMapper);
      LOGGER.info("Init on app ready complete..");
      //...
  }

编辑2(10/22):对于其他面临此挑战的人,

问题似乎是(由于下面的@M。Deinum),在ApplicationReadyEvent被触发及其事件处理程序被调用时似乎没有发生实例化和/或注入。对于我来说,这很奇怪,原因有两个,一个是根据文档,事件是"published as late as conceivably possible to indicate that the application is ready to service requests...since all initialization steps will have been completed by then",第二个是直到现在我还没有看到其他对象的其他注入导致这种行为,所以我从未怀疑这是原因。下面是一个片段,我在其中看到注射的效果

@Lazy
@Service
public class SampleServiceSingletonService {

  private static final Logger LOGGER = LoggerFactory.getLogger(SampleServiceSingletonService.class);

  @Autowired
  public ThreadPoolTaskScheduler threadPoolTaskScheduler;
  
  @Autowired
  public ThreadPoolTaskExecutor threadPoolTaskExecutor;
  
  @Autowired
  public ObjectMapper objectMapper;
  
  @EventListener(ApplicationReadyEvent.class)
  private void initOnAppReady() {
      // Its null here..
      //LOGGER.info("The Injected ObjectMapper: {}",objectMapper);
      LOGGER.info("Init on app ready complete..");
      runAsync();
  }
  
  @Async
  public void runAsync() {
      LOGGER.info("This is run asynchronously.");
      // Its no longer null here
      LOGGER.info("The Injected ObjectMapper: {}",objectMapper);
  }

}

谢谢

解决方法

您已经用@Lazy标记了bean。当放入一种类型时,将会为该对象创建一个惰性代理。在这种情况下,将创建一个基于类的代理(类上没有接口),并为此创建一个子类以添加懒惰行为。

但是,由于您的方法为private,因此无法在动态创建的类中覆盖此方法,因此将在代理上调用它,或者将其中继到实际对象。代理对象不会注入任何依赖性,至少不会注入private字段。

要解决此问题,请将方法protectedpublic设置为适当的子类并覆盖它。或者,如果不需要,请删除@Lazy

有关详细说明,请参见this blog

,

您应将settergetter添加到您的

     private ObjectMapper objectMapper;

因此Spring可以为其分配值