这篇文章介绍Spring 4的@Conditional注解。

一、在Spring的早期版本你可以通过以下方法来处理条件问题

  • 3.1之前的版本,使用Spring Expression Language(SPEL)。
  • 3.1版本有个新特性叫profile,用来解决条件问题。

1.1、Spring Expression Language(SPEL)

SPEL有一个三元运算符(if-then-else)可以在配置文件中当作条件语句,如下:

<bean id="flag">
<constructor-arg value="#{systemProperties['system.propery.flag'] ?: false }" />
</bean>
<bean id="testBean">
<property name="prop" value="#{ flag ? 'yes' : 'no' }"/>
</bean>

testBean的prop动态依赖于flag的值。

1.2、使用Profile

<!-- 如果没有设置profile,default.xml将被加载 -->
<!-- 必须放置在配置文件的最底下,后面再也没有bean的定义 -->
<beans profile="default">
<import resource="classpath:default.xml" />
</beans>
<!-- some other profile -->
<beans profile="otherProfile">
<import resource="classpath:other-profile.xml" />
</beans>

二、使用@Conditional

官方文档定义:“Indicates that a component is only eligible for registration when all specified conditions match”,意思是只有满足一些列条件之后创建一个bean

除了自己自定义Condition之外,Spring还提供了很多Condition给我们用

@ConditionalOnClass : classpath中存在该类时起效
@ConditionalOnMissingClass : classpath中不存在该类时起效
@ConditionalOnBean : DI容器中存在该类型Bean时起效
@ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
@ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
@ConditionalOnExpression : SpEL表达式结果为true时
@ConditionalOnProperty : 参数设置或者值一致时起效
@ConditionalOnResource : 指定的文件存在时起效
@ConditionalOnJndi : 指定的JNDI存在时起效
@ConditionalOnJava : 指定的Java版本存在时起效
@ConditionalOnWebApplication : Web应用环境下起效
@ConditionalOnNotWebApplication : 非Web应用环境下起效

@Conditional定义

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE, ElementType.METHOD)
public @interface Conditional{
Class<? extends Condition>[] value();
}

@Conditional注解主要用在以下位置:

  • 类级别可以放在注标识有@Component(包含@Configuration)的类上
  • 作为一个meta-annotation,组成自定义注解
  • 方法级别可以放在标识由@Bean的方法上

如果一个@Configuration的类标记了@Conditional,所有标识了@Bean的方法和@Import注解导入的相关类将遵从这些条件。

condition接口定义如下:

public interface Condition {

    /**
* Determine if the condition matches.
* @param context the condition context
* @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
* or {@link org.springframework.core.type.MethodMetadata method} being checked.
* @return {@code true} if the condition matches and the component can be registered
* or {@code false} to veto registration.
*/
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata); }

示例1:下面看一个例子:

结果:

 示例2:@ConditionalOnProperty来控制Configuration是否生效

Spring Boot通过@ConditionalOnProperty来控制Configuration是否生效

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty { String[] value() default {}; //数组,获取对应property名称的值,与name不可同时使用 String prefix() default "";//property名称的前缀,可有可无 String[] name() default {};//数组,property完整名称或部分名称(可与prefix组合使用,组成完整的property名称),与value不可同时使用 String havingValue() default "";//可与name组合使用,比较获取到的属性值与havingValue给定的值是否相同,相同才加载配置 boolean matchIfMissing() default false;//缺少该property时是否可以加载。如果为true,没有该property也会正常加载;反之报错 boolean relaxedNames() default true;//是否可以松散匹配,至今不知道怎么使用的
}
}

通过其两个属性name以及havingValue来实现的,其中name用来从application.properties中读取某个属性值。
如果该值为空,则返回false;
如果值不为空,则将该值与havingValue指定的值进行比较,如果一样则返回true;否则返回false。
如果返回值为false,则该configuration不生效;为true则生效。

@Configuration
//在application.properties配置"mf.assert",对应的值为true
@ConditionalOnProperty(prefix="mf",name = "assert", havingValue = "true")
public class AssertConfig {
@Autowired
private HelloServiceProperties helloServiceProperties;
@Bean
public HelloService helloService(){
HelloService helloService = new HelloService();
helloService.setMsg(helloServiceProperties.getMsg());
return helloService;
}
}
s

spring4.0之五:@Conditional在满足特定条件下,才会实例化对象的更多相关文章

  1. 特定条件下批量解压文件改变编码,顺便修改.so.0找不到等一些小问题

    直接结论: 1.linux解压文件乱码: unzip -O GBK *.zip 2.linux改变文件内容编码: 安装enca,下载地址:https://github.com/nijel/enca/i ...

  2. vue 特定条件下绑定事件

    今天写了个小功能,看起来挺简单,写的过程中发现了些坑.1.div没有disabled的属性,所以得写成button2.disabled在data时,默认是true,使得初始化时,默认置灰按钮,无法点击 ...

  3. @Conditional 注解,基于条件实例对象

    .catalogue-div { position: relative; background-color: rgba(255, 255, 255, 1); right: 0 } .catalogue ...

  4. js json 特定条件删除 增加 遍历

    <script type="text/javascript">        //直接声明json数据结构         var myJSONObject = [   ...

  5. [转]Struts2.3.16.1+Hibernate4.3.4+Spring4.0.2 框架整合

    原文地址:http://blog.csdn.net/ycb1689/article/details/22928519 最新版Struts2+Hibernate+Spring整合 目前为止三大框架最新版 ...

  6. Spring4.0编程式定时任务配置

    看过很多定时调度的配置,大多使用XML配置,觉得比较麻烦,也比较老套.这里介绍一种基于spring4.0注解编程式配置定时任务,简单清晰,使用方便.. 至于引入spring相关jar这里不多说,直接切 ...

  7. Spring4.0+Hibernate4.0+Struts2.3整合包括增删改查案例,解决整合中出现的异常

    源码下载:http://download.csdn.net/detail/cmcc_1234/7034775 ======================Application.xml======== ...

  8. Spring4.0支持Groovy配置

    介绍 前一段时间观注了一下Spring4.0的一些特性,当中就有对Groovy配置的支持.因为临时还没有很深入的研究.所以举个小样例来说明一下怎样支持Groovy配置. package shuai.s ...

  9. Spring4.0学习笔记(6) —— 通过工厂方法配置Bean

    1.静态工厂方法: bean package com.spring.factory; public class Car { public Car(String brand) { this.brand ...

随机推荐

  1. PTA——输出各位数字

    PTA 7-37 输出整数各位数字 方法1: #include <stdio.h> #define N 10000 int main(){ long n, temp; ; scanf(&q ...

  2. NDK: GCC 4.6 crashes

    used version: NDK r9b, arm-linux-androideabi-4.6 GCC,  with "-O2 -finline-limit=24". got t ...

  3. Easyui datagrid 去掉表头的checkbox复选框

    $(".datagrid-header-check").html(""); 在onLoadSuccess中加入此行代码即可实现datagrid去除表头的chec ...

  4. Django之JsonResponse

    JsonResponse 对象: class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=No ...

  5. MogileFS-2.44 安装与配置

    MogileFS-2.44 安装与配置 (转:https://my.oschina.net/u/1259000/blog/182277) 目录 一.MogileFS 介绍 1.1.环境 二.Mogil ...

  6. golang xml parent node add attribute without struct

    question: golang  encoding/xml: foo>bar,attr - foo ignored solution: you can replace output resul ...

  7. centos7之zabbix入门(一)

    初始化状态如下 首先按照下面的步骤进行,主机名和可见名可以自己起,dns那里最好也填一下,其它默认就可以了 点击确认后,自动跳转到以下页面 可以看到zbx那里没有亮起来,说明还没有配置成功,接下来点击 ...

  8. 这样学习C语言最有效(高级技巧)——共勉

    第一章 学习C语言的起跑线 1.1 C语言已死? 本资料描述的是使用C语言的高级技巧,力求将你的C语言能力由"基础"提升为"高级".但是学习态度胜过学习方法,在 ...

  9. KiCad 如何画板框

    KiCad 如何画板框 一块 PCB 最开始就是画板框. 设置工作到 Edge.Cuts 点菜单放置 -> 线(L) 板框画好.

  10. 使用apache cxf实现webservice服务

    1.在idea中使用maven新建web工程并引入spring mvc,具体可以参考https://www.cnblogs.com/laoxia/p/9311442.html; 2.在工程POM文件中 ...