今天主要从以下几方面来介绍一下@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. C# 发展史

    C# 发展史 Intro 本文主要总结介绍C# 每个版本带来的不同的语言特性. C#,读作C Sharp,是微软推出的一种基于.NET平台的.面向对象的高级编程语言.是微软公司在2000年发布的一种新 ...

  2. Struts标签库详解【3】

    struts2标签库详解 要在jsp中使用Struts2的标志,先要指明标志的引入.通过jsp的代码的顶部加入以下的代码: <%@taglib prefix="s" uri= ...

  3. idea 和 eclipse 常用快捷键汇总

    序号 所属类别 快捷键名称 快键键方式 备注 所属平台 1 查询类 search everywhere double shift    idea 2 全文搜索 ctrl + H   通用 3 打开资源 ...

  4. filddler一个抓包修改的工具 貌似很强大2017.12.07

    filddler直接百度下载  还没弄懂怎么用  有待研究!

  5. c# 编程语言tag

    ['JavaScript','Objective-C','C++','C#','Basic','PHP','Python','Perl', 'Transact-SQL','ruby','CSS3',' ...

  6. 你不知道的JavaScript--Item17 循环与prototype最后的几点小tips

    1.优先使用数组而不是Object类型来表示有顺序的集合 ECMAScript标准并没有规定对JavaScript的Object类型中的属性的存储顺序. 但是在使用for..in循环对Object中的 ...

  7. 巩固java(三)---java修饰符

    正文:               下面的表格列出了java中修饰符的一些信息: 修饰符名称 类型 类 变量 方法 abstract 非访问控制符 抽象类          -- 抽象方法 final ...

  8. bzoj5250 [2018多省省队联测]秘密袭击

    博主蒟蒻,目前还不会动态dp,所以下面说的是一个并不优秀的暴力,我会补的! 我们考虑按权值从大到小依次点亮每个点,相同权值可以同时点亮,每次点亮后,我们进行一次树形背包. 处理出$f[i][j]$表示 ...

  9. linux学习之路(1)

    Linux基础命令 命令格式:   命令名称  [参数]  [对象] 命令参数的长格式与短格式: 长格式:man -- help 短格式:man - h 常用系统工作命令 echo     输出语句  ...

  10. 自动化测试框架 hierarchyViewer、Uiautomator、Appium的区别比较!

    一.HierarchyViewer: 优点:1)能够可视化的角度直观地获得UI布局设计结构和各种属性的信息 2)使用hierarchyviewer.bat来检索手机界面布局 缺点:1)稳定性差,出现过 ...