1

Spring 可以使用s解析@ConfigurationClassReader

假设我们有以下场景

我们有一个具有多个@Bean定义的自动配置类

其中一个@Bean具有所有条件,而第二个@Bean具有@ConditionalOnClass并且该类不存在于类路径中

@Configuration
class CustomConfiguration {
  @Bean
  @ConditionalOnClass(String.class)
  String knownClass() {
    return "Hello";
  }

  @Bean
  @ConditionalOnClass(MissingClass.class)
  MissingClass secondBean() {
    return new MissingClass();
  }
}

在这种情况下,我有几个问题

  1. Spring Boot AutoConfiguration 是否将第一个 bean 注册到ApplicationContext?
  2. 如果 (1) 为真,我在第一个@Bean方法中的断点是否会在调试期间被命中
  3. 如果 (2) 为真,*AutoConfiguration该类如何加载到 JVM 中,因为该类将引用其他类(来自第二个 @Bean),这些类在类加载时无法解析
  4. 如果 (2) 为假,spring 是否在运行时仅使用第一个@Bean方法生成一个类并调用该方法?

谢谢

4

2 回答 2

3

一般来说,出于这个确切原因,您应该避免使用@ConditionalOnClass方法@Bean参考文档中介绍了这种情况,建议使用单独的@Configuration类来隔离@ConditionalOnClass条件。

要回答您的具体问题:

  1. 是的,只要配置类可以加载,第一个bean就会被注册
  2. 是的,第@Bean一种方法中的断点应该在调试期间命中
  3. 这取决于如何引用无法解析的类。如果它只在@Bean方法体内使用,则该类应该成功加载。如果在@Bean方法的签名(通常是返回类型)中使用了无法解析的类,则该类将无法加载。
  4. 不适用

@Configuration如上面链接的文档中所述,建议使用具有类级别条件的单独的、可能嵌套的类,而不是担心 3 中描述的场景以及哪些会起作用和不会起作用。对于您的具体示例,如下所示:

@Configuration
class CustomConfiguration {

  @Bean
  @ConditionalOnClass(String.class)
  String knownClass() {
    return "Hello";
  }

  @Configuration
  @ConditionalOnClass(MissingClass.class)
  static class DoubtfulBeanConfiguration {

    @Bean
    MissingClass missingClass() {
      return new MissingClass();
    }

  }

}
于 2019-02-05T14:37:19.457 回答
0

上面的安迪回答了“如何使用的问题”,即如何使用库。但在这个答案中,我试图回答为什么问题

这是我的理解

  1. Spring 从类路径中读取自动配置文件元数据/META-INF/spring-autoconfigure-metadata.properties(一个这样的文件存在于 中spring-boot-autoconfigure

    • 该文件由插件根据插件文件中的键@Configuration 下列出的类 生成org.springframework.boot.autoconfigure.EnableAutoConfiguration/META-INF/spring.factoriesspring-boot-autoconfigure-processor
    • 生成的文件包含@Configuration类级别的注释,例如@ConditionalOnClass,@AutoConfigureBefore等]
  2. Spring 构建关于@Configuration从上述属性文件中检索到的每个类的元数据
  3. 然后 Spring 评估所有@Configuration类级别条件,包括@ConditionalOnClass针对当前类路径和 bean 工厂。如果条件成功,它会@Configuration使用标准的 java 类加载来加载类
  4. 如果我们保持@ConditionalOnClass(MissingClass.class)@Configuration级别,如果类级别条件不评估为真,那么spring根本不会加载类加载配置类,如果类不在类路径中
  5. 但是如果我们保持@ConditionalOnClass(MissingClass.class)水平@Bean,spring 将尝试加载我们的@Configuration类(假设@Configuration类级别的所有条件都满足)并且我们将NoClassDefFoundError在类加载期间得到

总的来说,由于这个原因,我们需要遵循@Andy 解决方案

@安迪

感谢您是否可以就这是否是 Spring 在内部实现该@ConditionalOnClass功能的方式发表您的看法

谢谢

于 2019-02-05T15:06:26.233 回答