这篇文章介绍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. php 中使用正则

    1.匹配一个由一个小写字母和一位数字组成的字符串,比如”z2″   用^[a-z][0-9]$ 2.当在一组方括号里使用^是,它表示“非”或“排除”的意思   比如要求第一个字符不能是数字:^[^0- ...

  2. AangularJS入门总结一

    CRUD(增加Create.查询Retrieve.更新Update.删除Delete) 一.angularjs是为了克服HTML在构建应用上的不足而设计的: 二.AngularJS的出众之处: 构建一 ...

  3. Extend a root LVM partition online

    There is also a quick remedy for the emergency situation when your root partition runs out of disk s ...

  4. Python面试 【315+道题】

    Python面试 [315+道题] 第一部分 Python基础篇(80题) 为什么学习Python? 因为看到python的发展趋势,觉得需要与时俱进,第一点,python开发速度极快,能快速完成一个 ...

  5. log4net 自定义日志级别记录多个日志

    程序中原来只记录一个日志,现在我要写一个用户操作日志,需要与原来的日志分开,在config文件中一阵折腾无果(要么写不全,要么写重了,反正没办法完美分离,要么与现存代码没办法完美兼容),差点放弃准备自 ...

  6. Java解析property文件(和静哥说的,SQL执行限定时间写在xml中,增加扩展,在不改源代码基础上)

    在Java项目中一些配置参数保存在Property文件中,这样能保证不修改原代码直接修改Property文件. 简单的很,就是在java文件中读取外界的properyt配置文件 PropertyPar ...

  7. oracle数据库经常提示27102 out of memory解决方法

    网上有很多解决方案,但是我一个也看不懂,不知道写的什么鬼的东西,为什么一句话就能解决的事,非得长篇大论说原理是什么,看得一脸懵逼 我的解决方法入戏 vi /etc/sysctl.conf 修改kern ...

  8. MySQL--InnoDB并发线程控制

    InnoDB并发线程控制 MySQL InnoDB存储引擎提供innodb_thread_concurrency来控制进入InnoDB 存储引擎的线程数,以限制InnoDB存储引擎层的并发量. 当in ...

  9. sqler sql 转rest api 的docker 镜像构建(续)使用源码编译

    sqler 在社区的响应还是很不错的,已经添加了好多数据库的连接,就在早上项目的包管理还没有写明确, 下午就已经有go mod 构建的支持了,同时也调整下docker 镜像的构建,直接使用git cl ...

  10. UWA 技术分享连载 转载

    技术分享连载1 Q1:Texture占用内存总是双倍,这个是我们自己的问题,还是Unity引擎的机制? Q2:我现在发现两个因素直接影响Overhead,一个是Shader的复杂度,一个是空Updat ...