有时候会希望存在指定类型时才注入某个 Bean:
@AutoConfiguration
public class MyAutoConfiguration {@Bean@ConditionalOnClass(MyService.class)public MyConditionalBean statistics() {return new MyConditionalBean();}
}
但是如果按照上述代码,当MyService
不存在的时候,程序会直接找不到类,导致程序无法启动。
你会发现@ConditionalOnClass
用在被@Configuration
标注的类上,即使MyService
不存在,程序也会正常启动。但是像上面那样就不行。
这是因为和@Configuration
一起使用@ConditionalOnClass
时,其注解信息通过 ASM 解析,但是在处理和@Bean
一起用的@ConditionalOnClass
时,所在的配置类已经被 JVM 加载了,也就是加载在解析的前面,而要加载成功,首先要能够找到@ConditionalOnClass
所指明的类。
有两种解决方法:
-
指定全类名
@Bean @ConditionalOnClass(name ="com.example.MyService") public MyConditionalBean statistics() {return new MyConditionalBean(); }
-
内嵌配置类
@AutoConfiguration public class MyAutoConfiguration {@Configuration@ConditionalOnClass(MyService.class)public class MyConfiguration {@Beanpublic MyConditionalBean statistics() {return new MyConditionalBean();}} }
参考:Creating Your Own Auto-configuration :: Spring Boot、java - How does spring-boot @ConditionalOnClass work? - Stack Overflow