8.条件注入@ConditionalOnProperty

bean的条件注入,除了前面两篇博文分别介绍的通过@Conditional注解配合Condition接口的基本实现,以及如何使用条件注解@ConditionalOnBean@ConditionalOnClass

本文将主要介绍根据配置来决定是否创建bean的注解@ConditionalOnProperty

I. 配置属性作为条件

主要是根据配置参数,来决定是否需要创建这个bean,这样就给了我们一个根据配置来控制Bean的选择的手段了,如前面一篇博文中根据配置来选择是随机生成boolean还是随机生成int;只需要更改配置即可

1. @ConditionalOnProperty

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty {
	/**
	 * Alias for {@link #name()}.
	 * @return the names
	 */
	String[] value() default {};

	// 配置前缀
	String prefix() default "";

  // 配置名
	String[] name() default {};

	// 要求配置存在,且包含某个值
	String havingValue() default "";

	// 即便没有配置,也依然创建
	boolean matchIfMissing() default false;
}

2. 实例测试

a. 测试用例

测试几个常用的姿势,一是根据配置是否存在,来决定是否创建

public class PropertyExistBean {
    private String name;

    public PropertyExistBean(String name) {
        this.name = name;
    }

    public String getName() {
        return "property : " + name;
    }
}

public class PropertyNotExistBean {
    private String name;

    public PropertyNotExistBean(String name) {
        this.name = name;
    }

    public String getName() {
        return "no property" + name;
    }
}

对应的bean配置如下

/**
 * 配置存在时才会加载这个bean
 *
 * @return
 */
@Bean
@ConditionalOnProperty("conditional.property")
public PropertyExistBean propertyExistBean() {
    return new PropertyExistBean(environment.getProperty("conditional.property"));
}

/**
 * 即便配置不存在时,也可以加载这个bean
 *
 * @return
 */
@Bean
@ConditionalOnProperty(name = "conditional.property.no", matchIfMissing = true)
public PropertyNotExistBean propertyNotExistBean() {
    return new PropertyNotExistBean("conditional.property");
}

当配置存在,且value匹配时

public class PropertyValueExistBean {
    public String name;

    public PropertyValueExistBean(String name) {
        this.name = name;
    }

    public String getName() {
        return "property value exist: " + name;
    }
}

public class PropertyValueNotExistBean {
    public String name;

    public PropertyValueNotExistBean(String name) {
        this.name = name;
    }

    public String getName() {
        return "property value not exist: " + name;
    }
}

对应的配置如下

@Bean
@ConditionalOnProperty(name = {"conditional.property"}, havingValue = "properExists")
public PropertyValueExistBean propertyValueExistBean() {
    return new PropertyValueExistBean("properExists");
}

@Bean
@ConditionalOnProperty(name = {"conditional.property"}, havingValue = "properNotExists")
public PropertyValueNotExistBean propertyValueNotExistBean() {
    return new PropertyValueNotExistBean("properNotExists");
}

接下来就是配置的参数

conditional.property=properExists

b. 实例演示

根据前面的分析,上面的四个bean中,PropertyExistBean, PropertyNotExistBean, PropertyValueExistBean 应该存在;而PropertyValueNotExistBean 因为配置值不匹配,不会创建

测试代码如下

@RestController
@RequestMapping(path = "property")
public class PropertyRest {

    @Autowired(required = false)
    private PropertyExistBean propertyExistBean;
    @Autowired(required = false)
    private PropertyNotExistBean propertyNotExistBean;
    @Autowired(required = false)
    private PropertyValueExistBean propertyValueExistBean;
    @Autowired(required = false)
    private PropertyValueNotExistBean propertyValueNotExistBean;

    @GetMapping(path = "show")
    public String show() {
        Map<String, String> result = new HashMap<>(4);
        // 存在
        result.put("propertyExistBean", propertyExistBean == null ? "null ===> false" : propertyExistBean.getName());
        // 存在
        result.put("propertyNotExistBean",
                propertyNotExistBean == null ? "null ===> false" : propertyNotExistBean.getName());
        // 存在
        result.put("propertyValueExistBean",
                propertyValueExistBean == null ? "null ==> false" : propertyValueExistBean.getName());
        // 不存在
        result.put("propertyValueNotExistBean",
                propertyValueNotExistBean == null ? "null ==> true" : propertyValueNotExistBean.getName());
        return JSONObject.toJSONString(result);
    }
}

执行后结果如下,一如预期

gif.gif

II. 其他

0. 相关

a. 更多博文

基础篇

应用篇

b. 项目源码