@ConditionalOnXXXX系列注解
@Conditional 注解后,Spring4 又基于此注解推出了很多派生注解,如@ConditionalOnBean、@ConditionalOnMissingBean、@ConditionalOnExpression、@ConditionalOnClass 等。该系列使用方式和核心思想都差不多,下面我通过代码演示 @ConditionalOnBean 注解。
1. @ConditionalOnBean概念
使用场景:当需要注入的一个实体类,依赖于其他注入的实体类,就需要使用@ConditionalOnBean注解了。
2. @ConditionalOnBean定义
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {
// 需要作为条件的类的Class对象数组
Class<?>[] value() default {};
// 需要作为条件的类的Name,Class.getName()
String[] type() default {};
// (用指定注解修饰的bean)条件所需的注解类
Class<? extends Annotation>[] annotation() default {};
// spring容器中bean的名字
String[] name() default {};
// 搜索容器层级,当前容器,父容器
SearchStrategy search() default SearchStrategy.ALL;
// 可能在其泛型参数中包含指定bean类型的其他类
Class<?>[] parameterizedContainer() default {};
}
3. @ConditionalOnBean示例
3.1 创建一个Bean1
public class ConditionalBean1 {
private String name;
public ConditionalBean1() {
name = "my name is conditional bean1";
System.out.println("----------------my name is conditional bean1");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3.2 创建一个bean2
Bean2类中存在一个属性为bean1对象。(方便实现bean2注入依赖bean1)
public class ConditionalBean2 {
private ConditionalBean1 bean;
public ConditionalBean2() {
System.out.println("--------------------my name is conditional bean2");
}
public ConditionalBean1 getBean() {
return bean;
}
public void setBean(ConditionalBean1 bean) {
this.bean = bean;
}
}
3.3 注入
@Configuration
public class ConditionalConfig {
@Conditional({Conditional1.class})
@Bean
public ConditionalBean1 getConditionalBean1() {
return new ConditionalBean1();
}
@ConditionalOnBean({ConditionalBean1.class})
@Bean
public ConditionalBean2 getConditionalBean2(ConditionalBean1 bean) {
System.out.println(bean.getName());
ConditionalBean2 bean2 = new ConditionalBean2();
bean2.setBean(bean);
return bean2;
}
}
当Conditional1中的match函数返回true是,ConditionalBean1被注入,@ConditionalOnBean注解生效,自动注入ConditionalBean2;否则,不注入ConditionalBean2。
4. @ConditionalOnXXXX系列常用注解
- @ConditionalOnBean:当给定的在bean存在时,则实例化当前Bean
- @ConditionalOnMissingBean:当给定的在bean不存在时,则实例化当前Bean
- @ConditionalOnClass:当前classpath下存在指定类,则实例化当前Bean
- @ConditionalOnMissingClass:当前classpath下不存在指定类,则实例化当前Bean
- @ConditionalOnExpression:依赖于SpEL表达式值的条件元素的配置注释,条件为true,则实例化当前bean。如:
@ConditionalOnExpression("${redis.enabled}==1&&${redis.cluster.enabled:true}&&'${redis.name}'.equals('myredis')")
- @ConditionalOnWebApplication:当Spring为web服务时,才使注解的类生效;通常是配置类;
- @ConditionalOnProperty:通过@ConditionalOnProperty控制配置类是否生效,可以将配置与代码进行分离,实现了更好的控制配置。如:
@ConditionalOnProperty(prefix = "filter",name = "loginFilter",havingValue = "true")
,配置文件代码为filter.loginFilter=true
。@ConditionalOnProperty 实现是通过 havingValue 与配置文件中的值对比,返回为true则配置类生效,反之失效。 - @ConditionalOnResource:仅当指定的资源在类路径上时才生效。如:
@ConditionalOnResource(resources="classpath:jdbc.properties")