I am trying to use spring boot auto configuration feature and got an issue. I created a github repo to be able to reproduce easily the "issue": https://github.com/clembo590/spring-auto-configuration
just run mvn clean install
and you will get all the logs I am refering to in my description.
I have "enabled" the debug=true
spring boot property to see which 'autoconfiguration' is activated or not (and if it is not active why it is not active).
I also have added some logs to "log all the beans that have been added to the spring boot context".
Here is my autoConfiguration class.
@Configuration
@ComponentScan(basePackageClasses = MyClass.class)
@ConditionalOnBean(ObjectMapper.class)
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
public class CleaningAutoConfiguration {
@Bean
public Fake fake(){
return new Fake();
}
private static class Fake{
}
}
The very first weird thing is this log:
CleaningAutoConfiguration:
Did not match:
- @ConditionalOnBean (types: com.fasterxml.jackson.databind.ObjectMapper; SearchStrategy: all) did not find any beans of type com.fasterxml.jackson.databind.ObjectMapper (OnBeanCondition)
Matched:
- @ConditionalOnBean (types: com.fasterxml.jackson.databind.ObjectMapper; SearchStrategy: all) found bean 'jacksonObjectMapper' (OnBeanCondition)
First question: Why is @ConditionalOnBean BOTH matching and Not matching ? (my expectation about such a condition is that it should either match or not match... but not both... see question 5)
Now if we look at the logs it seems that CleaningAutoConfiguration
is in the Negative matches:
section.
Second question:
why is CleaningAutoConfiguration
itself registered as a bean ? (I was expecting it would not as it is in the Negative matches
section).
Third question:
Why is fake
still registered as a bean (I was expecting that fake
would not be registered, and not even instanciated...)
Fourth question:
why is MyClass
not registered as a bean ?
Now if you remove the @ComponentScan(basePackageClasses = MyClass.class)
then all those questions go away as CleaningAutoConfiguration
goes into Positive matches
section, but one new is created:
fifth question:
Why removing the @ComponentScan brings CleaningAutoConfiguration
into Positive matches
section ? (maybe question 5 is somehow connected to question 1 .... ?)
CodePudding user response:
The root cause of your problem is the use of @ComponentScan
on an auto-configuration class which is not supported:
Furthermore, auto-configuration classes should not enable component scanning to find additional components. Specific
@Import
s should be used instead.
To answer your specific questions:
Why is
@ConditionalOnBean
BOTH matching and not matching
It's first evaluated as part of considering the unsupported @ComponentScan
annotation. At this time, the ObjectMapper
bean has not been defined so it does not match. It's subsequently evaluated after the ObjectMapper
bean has been defined at which point it matches.
why is CleaningAutoConfiguration itself registered as a bean ? (I was expecting it would not as it is in the Negative matches section).
The report has mislead you here due to the positive and negative match. CleaningAutoConfiguration
is a bean due to the positive match.
Why is fake still registered as a bean (I was expecting that fake would not be registered, and not even instanciated...)
The report has misled you again. The conditions on CleaningAutoConfiguration
have been matched so its Fake
bean has been defined.
why is
MyClass
not registered as a bean
The conditions on CleaningAutoConfiguration
did not match when the @ComponentScan
annotation was being considered so component scanning of MyClass
's package was not enabled.
Why removing the
@ComponentScan
bringsCleaningAutoConfiguration
into Positive matches section
It prevents the conditions on CleaningAutoConfiguration
being evaluated prematurely at a time when the ObjectMapper
bean has not yet been defined. When they are eventually evaluated at the expected time, the ObjectMapper
bean is present and the conditions match.