问题描述
我看到在Spring Boot 2.3.4.RELEASE中注入Jackson ObjectMapper
时出现了怪异的行为。
我的maven依赖项中同时包含spring-boot-starter-web
和spring-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
字段。
要解决此问题,请将方法protected
或public
设置为适当的子类并覆盖它。或者,如果不需要,请删除@Lazy
。
有关详细说明,请参见this blog。
,您应将setter
和getter
添加到您的
private ObjectMapper objectMapper;
因此Spring可以为其分配值