Context
I know there are a lot of posts regarding the comparison between these two. All of them just focus on @Import
works on single Config file while @ComponenentScan
will scan all config, bean, service files.
I find something new, hope someone can give me a good explanation behind this:
Prerequisite Artifact:
- org.springframework.boot.autoconfigure
- org.springframework.boot.test
@SpringBootTest(classes = test1char.class)
@ComponentScan("org.springframework.boot.autoconfigure.jackson")
//@SpringBootTest(classes = test1char.class)
//@Import(org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.class)
public class ObjectMapperTest {
//cannot autowired: no such bean when using ComponenentScan
// Can autowired when either using @Import
// or @SpringBootTest(classes = org.springframework.boot.autoconfigure.jackson.class)
@Autowired
ObjectMapper objectMapper;
@Test
void main() {
var date = LocalDateTime.now();//LocalDateTime
String s;
try {
s = objectMapper.writeValueAsString(date);
System.out.println(s);
}catch (JsonProcessingException e){
System.out.println(e);
}
}
}
ObjectMapper bean producer class: org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.class for reference
@AutoConfiguration
@ConditionalOnClass({ObjectMapper.class})
public class JacksonAutoConfiguration {
.... omit
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({Jackson2ObjectMapperBuilder.class})
static class JacksonObjectMapperConfiguration {
JacksonObjectMapperConfiguration() {
}
@Bean
@Primary
@ConditionalOnMissingBean
ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
return builder.createXmlMapper(false).build();
}
}
Issue
Basically the ObjectMapper cannot autowired: no such bean when using ComponenentScan. But it can be autowired when either using @Import or @SpringBootTest(classes = org.springframework.boot.autoconfigure.jackson.class)
Note: test1char.class is just a dummy class so that it has a context while not using the default SpringBootApplication which has everything in class path
I know it must have something to do with ConditionalOnClass which requires some class in jar org.springframework.boot.autoconfigure.jackson to be in classpath. So I boldly guess only @Import and @SprngBoot and @SpringBootTest can load class or package to be in classpath? That's why quite often ObjectMapper cannot be autoconfigured in @SpringBootTest annotated integration test as we often forgot to add the jar to it.
Update
Hate to say with @EnableAutoConfiguration it works all good like below: @ComponentScan("org.springframework.boot.autoconfigure.jackson") @EnableAutoConfiguration
Update
Actually @EnableAutoConfiguration alone also works without @ComponentScan.
-- One who is always confused by SpringBoot config xD
Attachment: Condition Report output in Intellij when using @ComponenetScan
============================ CONDITIONS EVALUATION REPORT
Positive matches:
None
Negative matches:
None
Exclusions:
None
Unconditional classes:
None