简体   繁体   中英

How does spring-boot @ConditionalOnClass work?

How exactly does the @ConditionalOnClass annotation work?

My goal is to load a specific bean only if the jar providing this class is included in the classpath.

I thought the I could annotate a @Bean with @ConditionalOnClass(MyService.class) and declaring the dependency in maven as optional:

<dependency>
    <groupId>de.my</groupId>
    <artifactId>my-framework<artifactId>
    <optional>true</optional>
</dependency>

@Bean
@ConditionalOnClass(MyService.class)
public MyConditionalBean statistics() {
    return new MyConditionalBean();
}

Now, anyone having my-framework as dependency should get that bean automatically wired. But anyone not having the dependency should skip it.

But when I start the app, I get the following error:

Caused by: java.lang.ClassNotFoundException: de.MyService.class
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1702) ~[catalina.jar:7.0.50]
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1547) ~[catalina.jar:7.0.50]

So I'm probably doing something wrong. How can I then create the bean conditional on the dependency jars and the classes contained in the classpath?

From the spring docs:

The classes that must be present. Since this annotation parsed by loading class bytecode it is safe to specify classes here that may ultimately not be on the classpath.

But the error states different...

Good catch!

You can use on @Bean method level, but in that case you have to specify your class as a String literal:

@Bean
@ConditionalOnClass(name ="de.MyService")
public MyConditionalBean statistics() {
    return new MyConditionalBean();
}

I don't remeber already "why", but it is from an existing code of Spring Boot sources.

Now you can use curly branckets around the class name as it is an array:

//org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
    @ConditionalOnClass({Jackson2ObjectMapperBuilder.class})
    static class JacksonObjectMapperConfiguration {
        JacksonObjectMapperConfiguration() {
        }

        @Bean
        @Primary
        @ConditionalOnMissingBean
        ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
            return builder.createXmlMapper(false).build();
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM