今天主要从以下几方面来介绍一下@Conditional注解

  • @Conditional注解是什么

  • @Conditional注解怎么使用

1,@Conditional注解是什么

@Conditional注解是可以根据一些自定义的条件动态的选择是否加载该bean到springIOC容器中去,如果看过springBoot源码的同学会发现,springBoot中大量使用了该注解

2,@Conditional注解怎么使用

查看@Conditional源码你会发现它既可以作用在方法上,同时也可以作用在上,源码如下:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
/**
* All {@link Condition}s that must {@linkplain Condition#matches match}
* in order for the component to be registered.
*/
Class<? extends Condition>[] value();
}

设置给@conditional的类需要实现Condition接口

我们看一下Condition的源码:

public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}

ConditionContext源码:
public interface ConditionContext {
BeanDefinitionRegistry getRegistry(); ConfigurableListableBeanFactory getBeanFactory(); Environment getEnvironment(); ResourceLoader getResourceLoader(); ClassLoader getClassLoader();
}
AnnotatedTypeMetadata源码: 此类能够让我们检查带有@Bean注解的方法上还有其他什么注解
 public interface AnnotatedTypeMetadata { 

boolean isAnnotated(String var1); 
Map<String, Object> getAnnotationAttributes(String var1);
Map<String, Object> getAnnotationAttributes(String var1, boolean var2);
MultiValueMap<String, Object> getAllAnnotationAttributes(String var1);
MultiValueMap<String, Object> getAllAnnotationAttributes(String var1, boolean var2);
}
a,@Conditional作用在方法上

定义一个Condition如下:

/**
* 定义一个bean的Condition
*
* @author zhangqh
* @date 2018年5月1日
*/
public class MyCondition implements Condition {
public boolean matches(ConditionContext context,AnnotatedTypeMetadata metadata) {
Environment env = context.getEnvironment();
String system = env.getProperty("os.name");
System.out.println("系统环境为 ==="+system);
// 系统环境在Windows才加载该bean到容器中
if(system.contains("Windows")){
return true;
}
return false;
}
}

定义一个bean加上@Conditional注解如下:

@Conditional({MyCondition.class})
@Bean(value="user1")
public User getUser1(){
System.out.println("创建user1实例");
return new User("李四",26);
}

测试如下:

AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanNames = applicationContext2.getBeanDefinitionNames();
for(int i=0;i<beanNames.length;i++){
System.out.println("bean名称为==="+beanNames[i]);
}

运行结果:

bean名称为===mainConfig
bean名称为===user0
bean名称为===user1

我这边电脑系统是window所以user1实例是有创建出来的,如果把MyCondition中的判断改成if(system.contains("linux"))那么user1是不会加载到spring容器中的

b,@Conditional作用在类上

修改注解配置如下:

/**
* 定义一个注解配置文件 必须要加上@Configuration注解
*
* @author zhangqh
* @date 2018年4月30日
*/
@Conditional({MyCondition.class})
@Configuration
public class MainConfig {
/**
* 定义一个bean对象
* @return
*/
@Scope
@Lazy
@Bean(value="user0")
public User getUser(){
System.out.println("创建user实例");
return new User("张三",26);
}
//@Conditional({MyCondition.class})
@Bean(value="user1")
public User getUser1(){
System.out.println("创建user1实例");
return new User("李四",26);
}
}

运行测试:

bean名称为===mainConfig
bean名称为===user0
bean名称为===user1

MainConfig中的bean都成功打印出来了,因为我MyCondition条件返回的是true,同样如果我修改成if(system.contains("linux"))那么MainConfig的bean就都不会实例化了

c, @profile注解分析
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({ProfileCondition.class})
public @interface Profile {
String[] value();
}

注意:@Profile本身也使用了@Condition注解,并且引用ProfileCondition作为Condition的实现。

以下为ProfileCondition的实现

class ProfileCondition implements Condition {
ProfileCondition() {
} public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
if (context.getEnvironment() != null) {
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
Iterator var4 = ((List)attrs.get("value")).iterator(); Object value;
do {
if (!var4.hasNext()) {
return false;
} value = var4.next();
} while(!context.getEnvironment().acceptsProfiles((String[])((String[])value))); return true;
}
} return true;
}
}

Spring中的@conditional注解的更多相关文章

  1. 四、Spring中使用@Conditional按照条件注册Bean

    以前其实是写过@Condtional注解的笔记的,这里附上链接: Spring中的@conditional注解 但已经忘记的差不多了,所以今天再重新学习下,可以互补着学习 @Contional:按照一 ...

  2. 第5章—构建Spring Web应用程序—关于spring中的validate注解后台校验的解析

    关于spring中的validate注解后台校验的解析 在后台开发过程中,对参数的校验成为开发环境不可缺少的一个环节.比如参数不能为null,email那么必须符合email的格式,如果手动进行if判 ...

  3. Spring 中aop切面注解实现

    spring中aop的注解实现方式简单实例   上篇中我们讲到spring的xml实现,这里我们讲讲使用注解如何实现aop呢.前面已经讲过aop的简单理解了,这里就不在赘述了. 注解方式实现aop我们 ...

  4. Spring中的常用注解

    Spring中的常用注解 1.@Controller 标识一个该类是Spring MVC controller处理器,用来创建处理http请求的对象.

  5. JavaEE开发之Spring中的条件注解组合注解与元注解

    上篇博客我们详细的聊了<JavaEE开发之Spring中的多线程编程以及任务定时器详解>,本篇博客我们就来聊聊条件注解@Conditional以及组合条件.条件注解说简单点就是根据特定的条 ...

  6. JavaEE开发之Spring中的条件注解、组合注解与元注解

    上篇博客我们详细的聊了<JavaEE开发之Spring中的多线程编程以及任务定时器详解>,本篇博客我们就来聊聊条件注解@Conditional以及组合条件.条件注解说简单点就是根据特定的条 ...

  7. Spring中常用的注解,你知道几个呢?

    今天给大家分享下Spring中一般常用的注解都有哪些.可能很多人做了很长是了但有些还是不知道一些注解,不过没有关系,你接着往下看. Spring部分 1.声明bean的注解 @Component 组件 ...

  8. Spring中的Autowired注解和Resource注解的区别

    1.所属jar包不同,Autowired是Spring中的Resource是JSR-250规范定义的注解

  9. 深入理解spring中的各种注解

    Spring中的注解大概可以分为两大类: 1)spring的bean容器相关的注解,或者说bean工厂相关的注解: 2)springmvc相关的注解. spring的bean容器相关的注解,先后有:@ ...

随机推荐

  1. 关于ajax原理阐述

    ajax是什么呢?说白了就是一个请求,一个读取服务器资源以及提交资源到服务器的中间处理机制,那它具体是怎样工作的,又有怎样的原理呢?var ajax=function(url,fnSucceed,fn ...

  2. .NET开发微信小程序-微信支付

    前台MD5加密代码 /* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algor ...

  3. arcEngine开发之根据点坐标创建Shp图层

    思路 根据点坐标创建Shapefile文件大致思路是这样的: (1)创建表的工作空间,通过 IField.IFieldsEdit.IField 等接口创建属性字段,添加到要素集中. (2)根据获取点的 ...

  4. C Primer Plus 第8章 字符输入/输出和验证输入 编程练习

    1. #include <stdio.h> int main(){ char ch; int ct = 0; while ((ch=getchar()) != EOF) ct++; pri ...

  5. 不使用JavaScript实现菜单的打开和关闭

    我在写有菜单栏的网页时,基本都会用响应式设计来适配移动端,例如把不重要的菜单选项隐藏,或者创建一个菜单按钮来控制的菜单的打开和关闭之类的.而我之前一直是使用JavaScript来实现菜单的打开和关闭的 ...

  6. PAT1056:Mice and Rice

    1056. Mice and Rice (25) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Mice an ...

  7. Js的String对象

    Js的String对象常用方法: 方法一.得到某字符在字符串中的索引位置. str.indexOf(findStr,[index])--返回的是要查找字符在字符串中的位置索引   ,index开始查找 ...

  8. InnoDB存储引擎结构介绍

    Ⅰ.InnoDB发展史 时间 事件 备注 1995 由Heikki Tuuri创建Innobase Oy公司,开发InnoDB存储引擎 Innobase开始做的是数据库,希望卖掉该公司 1996 My ...

  9. Dubbo源码-Dubbo是如何随心所欲自定义XML标签的

    叨叨 今天考虑了很久要不要写这篇文章. 距离<Dubbo源码>系列的开篇到现在已经快两个月时间了.当时是想着工作上的RPC框架使用存在一些让人头疼的问题,就来看看Dubbo给出了一套什么样 ...

  10. Python将html转化为pdf

    前言 前面我们对博客园的文章进行了爬取,结果比较令人满意,可以一下子下载某个博主的所有文章了.但是,我们获取的只有文章中的文本内容,并且是没有排版的,看起来也比较费劲... 咋么办的?一个比较好的方法 ...