Spring可以使用@Configuration
s来解析ClassReader
类
假设我们有以下情况
我们有一个带有多个@Bean
定义的自动配置类
其中一个@Bean
已通过所有条件,而第二个@Bean
具有@ConditionalOnClass
并且该类不在类路径中
@Configuration
class CustomConfiguration {
@Bean
@ConditionalOnClass(String.class)
String knownClass() {
return "Hello";
}
@Bean
@ConditionalOnClass(MissingClass.class)
MissingClass secondBean() {
return new MissingClass();
}
}
在这种情况下,我有几个问题
ApplicationContext
中?@Bean
方法中遇到我的断点*AutoConfiguration
类将如何加载到JVM中,因为此类将引用其他类(来自第二个@Bean),这些类在类加载时无法解析@Bean
方法生成一个类并调用该方法?谢谢
答案 0 :(得分:3)
通常来说,出于这个确切原因,您应该避免在@ConditionalOnClass
方法上使用@Bean
。 reference documentation涵盖了这种情况,建议使用单独的@Configuration
类来隔离@ConditionalOnClass
条件。
要回答您的特定问题:
@Bean
方法中设置一个断点@Bean
方法的主体内使用它,则该类应成功加载。如果在@Bean
方法的签名中使用了无法解析的类(通常是返回类型),则该类将无法加载。如上面链接的文档中所述,建议不要担心3中描述的场景以及什么会起作用,什么不起作用,建议使用带有类级别条件的单独的,可能嵌套的@Configuration
类方法。对于您的特定示例,应如下所示:
@Configuration
class CustomConfiguration {
@Bean
@ConditionalOnClass(String.class)
String knownClass() {
return "Hello";
}
@Configuration
@ConditionalOnClass(MissingClass.class)
static class DoubtfulBeanConfiguration {
@Bean
MissingClass missingClass() {
return new MissingClass();
}
}
}
答案 1 :(得分:0)
上面的Andy回答了“如何提问”,即如何使用该库。但是在这个答案中,我试图回答为什么这个问题
这是我的理解
Spring从类路径的/META-INF/spring-autoconfigure-metadata.properties
中读取自动配置文件元数据(spring-boot-autoconfigure
中存在一个这样的文件)
@Configuration
的插件生成的
列出的课程
org.springframework.boot.autoconfigure.EnableAutoConfiguration
键
/META-INF/spring.factories
插件在spring-boot-autoconfigure-processor
文件中添加@Configuration
类级别的注释,例如@ConditionalOnClass
,@AutoConfigureBefore
,
e.t.c] @Configuration
类构建元数据@Configuration
类级别的条件,包括@ConditionalOnClass
。如果条件成功,它将使用标准java类加载来加载@Configuration
类@ConditionalOnClass(MissingClass.class)
保持在@Configuration
级别,则在类级别条件未评估为true的情况下,spring不会简单地将类加载到配置类中,例如,如果该类不在classpath中@ConditionalOnClass(MissingClass.class)
保持在@Bean
级别,spring将尝试加载我们的@Configuration
类(假设满足@Configuration
类级别的所有条件)并且我们将在类加载期间获取NoClassDefFoundError
总体而言,由于这个原因,我们需要遵循@Andy解决方案
@安迪
请您欣赏一下Spring是否内部实现了@ConditionalOnClass
功能的视图
谢谢