I created a minimalist Spring Boot project with only spring-boot-starter-web
as a dependency.
On my classpath I have spring-boot-autoconfigure
JAR, that has preconfigured many different technologies, e.g. CassandraAutoConfiguration
. Obviously, in the runtime, this autoconfiguration won't spin up any beans since the conditions won't match (because I don't have anything related to Cassandra on my classpath.
How does Spring Boot handle the following?
spring-boot-autoconfigure
JAR so that it doesn't fail during compilation even though the dependencies for things like CassandraAutoConfiguration
are missing?
My assumption is that Spring Boot includes all the necessary dependencies during compilation but simply doesn't package them into the final JAR.CassandraAutoConfiguration
at runtime: How does Spring Boot manage to load CassandraAutoConfiguration
even when many of the classes it references are missing on the classpath? Why doesn't this result in runtime failures?
I found the answer in @ConditionalOnClass
java docs:
/**
* {@link Conditional @Conditional} that only matches when the specified classes are on
* the classpath.
* <p>
* A {@code Class} {@link #value() value} can be safely specified on
* {@code @Configuration} classes as the annotation metadata is parsed by using ASM before
* the class is loaded. If a class reference cannot be used then a {@link #name() name}
* {@code String} attribute can be used.
* <p>
...
*/
public @interface ConditionalOnClass {
/**
* The classes that must be present. Since this annotation is parsed by loading class
* bytecode, it is safe to specify classes here that may ultimately not be on the
* classpath, only if this annotation is directly on the affected component and
* <b>not</b> if this annotation is used as a composed, meta-annotation. In order to
* use this annotation as a meta-annotation, only use the {@link #name} attribute.
* @return the classes that must be present
*/
Class<?>[] value() default {};
...
}
So, as far as I understand, the reason the evaluation of @ConditionalOnClass
doesn't fail in runtime is because, Spring doesn't use reflection. Instead, it reads files bytecode.