使用条件注解@ConditionalOnBean
和@ConditionalOnClass
本文将主要介绍根据配置来决定是否创建bean的注解@ConditionalOnProperty
I. 配置属性作为条件
主要是根据配置参数,来决定是否需要创建这个bean,这样就给了我们一个根据配置来控制Bean的选择的手段了,如前面一篇博文中根据配置来选择是随机生成boolean还是随机生成int;只需要更改配置即可
1. @ConditionalOnProperty
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) @Documented @Conditional(OnPropertyCondition.class) public @interface ConditionalOnProperty { true/** * Alias for {@link #name()}. * @return the names */ trueString[] value() default {}; true// 配置前缀 trueString prefix() default ""; // 配置名 trueString[] name() default {}; true// 要求配置存在,且包含某个值 trueString havingValue() default ""; true// 即便没有配置,也依然创建 trueboolean matchIfMissing() default false; } |
2. 实例测试
a. 测试用例
测试几个常用的姿势,一是根据配置是否存在,来决定是否创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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配置如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /** * 配置存在时才会加载这个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匹配时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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; } } |
对应的配置如下
1 2 3 4 5 6 7 8 9 10 11 | @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"); } |
接下来就是配置的参数
1 | conditional.property=properExists |
b. 实例演示
根据前面的分析,上面的四个bean中,PropertyExistBean
, PropertyNotExistBean
, PropertyValueExistBean
应该存在;而PropertyValueNotExistBean
因为配置值不匹配,不会创建
测试代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | @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); } } |
执行后结果如下,一如预期
基于SPEL表达式的条件注解ConditionalOnExpression
IV. 表达式条件注入
相比较前面的Bean,Class是否存在,配置参数是否存在或者有某个值而言,这个依赖SPEL表达式的,就显得更加的高级了;其主要就是执行Spel表达式,根据返回的true/false来判断是否满足条件
至于SPEL是什么东西,后面会有专文进行解释,此处不加以展开。下面以一个简单的demo进行演示它的使用姿势
1. @ConditionalOnExpression
接口定义
1 2 3 4 5 6 7 8 9 10 11 12 13 | @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) @Documented @Conditional(OnExpressionCondition.class) public @interface ConditionalOnExpression { true/** true * The SpEL expression to evaluate. Expression should return {@code true} if the true * condition passes or {@code false} if it fails. true * @return the SpEL expression true */ trueString value() default "true"; } |
2. 实例测试
用一个简单的例子,当配置参数中,根据是否满足某个条件来决定是否需要加载bean
a. 测试用例
定义一个满足条件和一个不满足的bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class ExpressFalseBean { private String name; public ExpressFalseBean(String name) { this.name = name; } public String getName() { return "express bean :" + name; } } public class ExpressTrueBean { private String name; public ExpressTrueBean(String name) { this.name = name; } public String getName() { return "express bean :" + name; } } |
重点关注下bean的配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @Configuration public class ExpressAutoConfig { /** * 当存在配置,且配置为true时才创建这个bean * @return */ @Bean @ConditionalOnExpression("#{'true'.equals(environment['conditional.express'])}") public ExpressTrueBean expressTrueBean() { return new ExpressTrueBean("express true"); } /** * 配置不存在,或配置的值不是true时,才创建bean * @return */ @Bean @ConditionalOnExpression("#{!'true'.equals(environment.getProperty('conditional.express'))}") public ExpressFalseBean expressFalseBean() { return new ExpressFalseBean("express != true"); } } |
对应的配置如下
1 | conditional.express=true |
b. 实例演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @RestController @RequestMapping(path = "express") public class ExpressRest { @Autowired(required = false) private ExpressTrueBean expressTrueBean; @Autowired(required = false) private ExpressFalseBean expressFalseBean; @GetMapping(path = "show") public String show() { Map<String, String> result = new HashMap<>(4); result.put("expressTrueBean", expressTrueBean == null ? "null ==> false" : expressTrueBean.getName()); result.put("expressFalseBean", expressFalseBean == null ? "null ==> true": expressFalseBean.getName()); return JSONObject.toJSONString(result); } } |
上面的执行,expressTrueBean
应该存在,另外一个为null,运行结果如下