I understand that Spring Boot has lots of @Conditional
annotations like, @ConditionalOnBean
, @ConditionalOnClass
, @ConditionalOnProperty
, ConditionalOnWebApplication
. But I do not know how this work?
For Example:
@Configuration
@ConditionalOnClass(MyBean.class)
public class MyConfiguration{
// omitted
}
What I understood is, MyConfiguration
will be loaded only if MyBean
is available in my classpath. But how would it compile and run if MyBean
class is not in my class path as the compiler reaches to @ConditionalOnClass(MyBean.class)
line, wont it throw compiler error? As soon as I add such code in my eclipse, I am getting compile time error. Sorry if this is too basic question but I do not know what I am missing to understand.
Spring Boot is being compiled with lots of optional dependencies; so when Spring Boot is compiled, the MyBean.class
is on the classpath.
Now your application may not have that MyBean.class
in its classpath, but it doesn't fail at runtime. This is because the infrastructure that processes @ConditionalOnClass
annotations will actually read the bytecode of the configuration and will only load them if that MyBean.class
is present. See @ConditionalOnClass
javadoc.
Now auto-configuration is a broad subject, and you can learn more about this in this talk.
As the Spring Boot Documentation says:
The @ConditionalOnClass and @ConditionalOnMissingClass annotations allows configuration to be included based on the presence or absence of specific classes. Due to the fact that annotation metadata is parsed using ASM you can actually use the value attribute to refer to the real class, even though that class might not actually appear on the running application classpath. You can also use the name attribute if you prefer to specify the class name using a String value.
So they use the bytecode manipulation library ASM to be able to parse the class names during runtime, even if the classes are not anymore on the classpath. Since Spring is open source, you can even just go look at the annotation reading code.
You would typically use Optional
dependencies:
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<optional>true</optional>
</dependency>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With