@ConditionalOnMissingBean与@ConditionalOnBean
俩个作用:根据当前环境或者容器情况来动态注入bean,要配合@Bean使用
@ConditionalOnMissingBean作用:判断当前需要注入Spring容器中的bean的实现类是否已经含有,有的话不注入,没有就注入
@ConditionalOnBean作用:判断当前需要注册的bean的实现类否被spring管理,如果被管理则注入,反之不注入
源码:
@ConditionalOnMissingBean和@ConditionalOnBean
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({OnBeanCondition.class})
public @interface ConditionalOnBean {
Class<?>[] value() default {};
String[] type() default {};
Class<? extends Annotation>[] annotation() default {};
String[] name() default {};
SearchStrategy search() default SearchStrategy.ALL;// bean工厂层次结构中bean的一些命名搜索策略
Class<?>[] parameterizedContainer() default {};
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({OnBeanCondition.class})
public @interface ConditionalOnMissingBean {
Class<?>[] value() default {};
String[] type() default {};
Class<?>[] ignored() default {};
String[] ignoredType() default {};
Class<? extends Annotation>[] annotation() default {};
String[] name() default {};
SearchStrategy search() default SearchStrategy.ALL;
Class<?>[] parameterizedContainer() default {};
}
可以发现@ConditionalOnMissingBean和@ConditionalOnBean俩个注解的动态注入条件判断类都是OnBeanCondition,并且都是基于@Conditional注解。
@Conditional具体可以去看 @Conditional注解使用与自定义验证注解 这篇文章
OnBeanCondition:
@Order(2147483647)
class OnBeanCondition extends FilteringSpringBootCondition implements ConfigurationCondition {
...具体内容可以看代码
}
OnBeanCondition没有直接实现matches方法,而是使用的FilteringSpringBootCondition的父类SpringBootCondition类中的matches方法。
demo:
-
创建接口Animal
public interface Animal { String eat(); }
-
分别创建俩个实现类
public class Dog implements Animal { @Override public String eat() { return "肉"; } } public class Cat implements Animal { @Override public String eat() { return "老鼠"; } }
-
创建俩个配置类
@Configuration public class CatConfig { @Bean public Animal animal() { return new Cat(); } } @Configuration public class DogConfig { @Bean public Animal animal() { return new Cat(); } }
-
测试类
@SpringBootApplication public class ServiceDiscoverApplication implements CommandLineRunner { @Autowired private Animal animal; public static void main(String[] args) { SpringApplication.run(ServiceDiscoverApplication.class, args); } //测试方法 @Override public void run(String... args) throws Exception { String eat = animal.eat(); System.out.println(eat); } }
-
测试
-
@ConditionalOnMissingBean
修改配置类,在CatConfig中添加@ConditionalOnMissingBean注解
@Configuration public class CatConfig { @Bean @ConditionalOnMissingBean public Animal animal() { return new Cat(); } } 运行程序:控制台输出为 '肉' 当在DogConfig中添加@ConditionalOnMissingBean注解,运行结果为 '老鼠' 如果当前容器中含有Animal类型的bean,那么就不加载带有@ConditionalOnMissingBean注解的Animal类型bean到spring的ioc容器。
-
@ConditionalOnBean
修改Cat类,去掉@Service,不让spring管理
public class Cat implements Animal { @Override public String eat() { return "老鼠"; } }
修改CatConfig类,在CatConfig中添加@ConditionalOnBean注解
@Configuration public class CatConfig { @Bean @ConditionalOnBean(Cat.class) public Animal animal() { return new Cat(); } } 运行程序:控制台输出为 '肉' 当在DogConfig中添加@ConditionalOnBean(Dog.class)注解、去掉@Service注解时,运行结果为 '老鼠' 当bean Animal的实现类没有被spring所管理,那么就不会加载带有@ConditionalOnBean注解的bean到spring的ioc容器。
-