上文我们讲解了@Import的方式进行导入,本文我们将学习@Conditional xxx相关注解
主要有:
@Conditional // 根据条件判断满足时,则实例化当前Bean
@ConditionalOnBean // 当给定的在bean存在时,则实例化当前Bean
@ConditionalOnMissingBean // 当给定的在bean不存在时,则实例化当前Bean
@ConditionalOnClass // 当给定的类名在类路径上存在,则实例化当前Bean
@ConditionalOnMissingClass // 当给定的类名在类路径上不存在,则实例化当前Bean
一.@Conditional
public @interface Conditional {
Class<? extends Condition>[] value();
}
根据源码我们使用此注解时,value的时需要继承Condition接口
假设:
bule这个Bean存在我们就实例化SuperMan
bule01这个Bean存在我们就实例化Man
这时我们就可以采用 @Conditional进行管理
1.1 定义相关类
@Data
public class SuperMan {
private String name;
private Integer age;
}
---------
@Data
public class Man {
private String userName;
private String email;
}
--------
@Data
public class Bule {
private Integer code;
}
1.2 定义配置文件
1.2.1 定义Bean实例化文件
@Configuration
public class MainConfig {
@Bean(value = "bule01")
public Bule bule(){
return new Bule();
}
@Bean
@Conditional(value = SueperManCondition.class)
public SuperMan superMan(){
return new SuperMan("Javayh",27);
}
@Bean
@Conditional(value = ManCondition.class)
public Man man(){
return new Man("Javayh","javayh@javayh.com");
}
}
1.2.2 定义Bean实例化条件
public class ManCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {
//获取到bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
//可以判断容器中的bean注册情况,也可以给容器中注册bean
boolean definition = registry.containsBeanDefinition("bule01");
if(definition){
return true;
}
return false;
}
}
--------
public class SueperManCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {
//获取到bean定义的注册类
BeanDefinitionRegistry registry = context.getRegistry();
//可以判断容器中的bean注册情况,也可以给容器中注册bean
boolean definition = registry.containsBeanDefinition("bule");
if(definition){
return true;
}
return false;
}
}
1.2.3 验证
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
@Test
public void testCondtion(){
printBeans(applicationContext);
Bule bule = applicationContext.getBean(Bule.class);
System.out.println(bule);
SuperMan bean = applicationContext.getBean(SuperMan.class);
System.out.println(bean);
Man man = applicationContext.getBean(Man.class);
System.out.println(man);
}
private void printBeans(AnnotationConfigApplicationContext applicationContext){
String[] definitionNames = applicationContext.getBeanDefinitionNames();
for (String name : definitionNames) {
System.out.println(name);
}
}
运行之后我们发现,实例化bule01存在,这是根据条件将实例化man 这个Bean,而无法实例化 SuperMan
二.@ConditionalOnBean
源码可以看出,也用到了 @Conditional
@Conditional({OnBeanCondition.class})
public @interface ConditionalOnBean {
//指定 条件的 Bean.Class
Class<?>[] value() default {};
//作为条件的类的Name,Class.getName()
String[] type() default {};
//条件所需的注解类
Class<? extends Annotation>[] annotation() default {};
//容器中bean的名字
String[] name() default {};
//搜索容器层级,当前容器,父容器
SearchStrategy search() default SearchStrategy.ALL;
//可能在其泛型参数中包含指定bean类型的其他类
Class<?>[] parameterizedContainer() default {};
}
2.1 定义Bean
接下来我们修改上面的方放,当Bule作为SuperMan的变量
@Data
@AllArgsConstructor
public class SuperMan {
private String name;
private Integer age;
private Bule bule;
}
2.2 定义Bean实例化规则
这是我们需要根据Bule是否在容器内,来进行SuperMan的实例化,做到Bule存在则SuperMan存在,否则不存在
@Configuration
public class MainConfig {
@Bean(value = "bule")
public Bule bule(){
return new Bule();
}
@Bean
@ConditionalOnBean(value = Bule.class)
public SuperMan superMan(Bule bule){
bule.setCode(123);
return new SuperMan("Javayh",27,bule);
}
@Bean
@Conditional(value = ManCondition.class)
public Man man(){
return new Man("Javayh","javayh@javayh.com");
}
}
2.3 测试
@Test
public void testCondtionOnBean(){
printBeans(applicationContext);
SuperMan bean = applicationContext.getBean(SuperMan.class);
System.out.println(bean);
}
Bule存在容器中,SuperMan被实例化
这时我们可以将Bule的实例化注释掉,在进行测试,时容器内并没有Bule,而SuperMan也没 被实例化,我们书getBean就会错
@ConditionalOnMissingBean 其实与@ConditionalOnBean正好相反,这里就不做测试了
三.@ConditionalOnClass
public @interface ConditionalOnClass {
//指定 条件的 Bean.Class
Class<?>[] value() default {};
//条件bean的名称
String[] name() default {};
}
其实不难发现 ConditionalOnClass 和 ConditionalOnBean 左右是一样的,这是我们将 ConditionalOnBean 的例子改一下
@Bean
@ConditionalOnClass(value = Bule.class)
public SuperMan superMan(Bule bule){
bule.setCode(123);
return new SuperMan("Javayh",27,bule);
}
结果是一样
扩展
@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
@ConditionalOnNotWebApplication(不是web应用)
本文的分享暂时就到这里,希望对您有所帮助
关注 Java有货领取更多资料
联系小编。微信:372787553,带您进群互相学习
左侧小编微信,右侧获取免费资料
- SpringCloud 自定义封装架构https://github.com/Dylan-haiji/javayh-platform
- Java 设计模式学习代码 https://github.com/Dylan-haiji/design-pattern
- SpringCloud学习代码: https://github.com/Dylan-haiji/javayh-cloud
- AlibabaCloud学习代码:https://github.com/Dylan-haiji/javayh-cloud-nacos
- SpringBoot+Mybatis 多数据源切换:https://github.com/Dylan-haiji/javayh-boot-data-soure
- Redis、Mongo、Rabbitmq、Kafka学习代码: https://github.com/Dylan-haiji/javayh-middleware
- SpringBoot+SpringSecurity实现自定义登录学习代码:https://github.com/Dylan-haiji/javayh-distribution