【问题标题】:How does spring-boot @ConditionalOnClass work?spring-boot @ConditionalOnClass 是如何工作的?
【发布时间】:2023-03-30 18:16:01
【问题描述】:

@ConditionalOnClass 注释究竟是如何工作的?

我的目标是仅当提供此类的jar 包含在类路径中时才加载特定的bean。

我认为我可以用 @ConditionalOnClass(MyService.class) 注释 @Bean 并将 maven 中的依赖项声明为可选:

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

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

现在,任何将 my-framework 作为依赖项的人都应该自动连接该 bean。但是任何没有依赖关系的人都应该跳过它。

但是当我启动应用程序时,我收到以下错误:

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]

所以我可能做错了什么。然后如何根据依赖项 jar 和类路径中包含的类创建 bean?

来自春季文档:

必须存在的类。由于此注释由 加载类字节码 在这里指定类是安全的 最终不在类路径上。

但错误状态不同...

【问题讨论】:

    标签: java spring spring-boot


    【解决方案1】:

    好收获!

    您可以在@Bean 方法级别上使用,但在这种情况下,您必须将您的类指定为字符串文字:

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

    我不记得“为什么”了,但它来自 Spring Boot 源代码的现有代码。

    【讨论】:

    • 如果你把它放在一个顶级类中,我会在类加载时将其拉入的类除外。那是在使用类的时候。将其用作字符串文字可以防止这种情况发生。
    • 请注意,如果它是在类级别声明的,则不必是字符串文字。去搞清楚。 docs.spring.io/spring-boot/docs/current/api/org/springframework/…
    猜你喜欢
    • 2016-12-29
    • 1970-01-01
    • 2021-03-10
    • 2021-05-21
    • 2019-01-27
    • 2021-08-17
    • 2018-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多