二、Spring注解之@Conditional
Spring注解之@Conditional
【1】@Conditional介绍
@Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,满足条件给容器注册bean。
@Conditional源码:
//此注解可以标注在类和方法上
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}
从代码中可以看到,需要传入一个Class数组,并且需要继承Condition接口:
public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}
Condition是个接口,需要实现matches方法,返回true则注入bean,false则不注入。
【2】@Conditional示例
首先,创建Person类:
public class Person {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
创建MyConfig类,用于配置两个Person实例并注入,一个是Bill Gates,一个是linus。
@Configuration
public class MyConfig {
@Bean(name = "bill")
public Person person1(){
return new Person("Bill Gates",62);
}
@Bean("linus")
public Person person2(){
return new Person("Linus",48);
}
}
写一个测试类,测试是否注入成功
public class ConditionalTest {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
@Test
public void test1(){
Map<String, Person> map = applicationContext.getBeansOfType(Person.class);
System.out.println(map);
}
}
/**测试结果
{bill=Person{name='Bill Gates',age=62},linus=Person{name='Linus',age='48'}}
*/
这是一个简单的例子,现在问题来了,如果我想根据当前操作系统来注入Person实例,windows下注入bill,linux下注入linus,怎么实现呢?
这就需要我们用到@Conditional注解了,前言中提到,需要实现Condition接口,并重写方法来自定义match规则。
首先,创建一个WindowsCondition类:
public class WindowsCondition implements Condition {
/**
* @param conditionContext:判断条件能使用的上下文环境
* @param annotatedTypeMetadata:注解所在位置的注释信息
* */
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//获取ioc使用的beanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//获取类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
//获取当前环境信息
Environment environment = conditionContext.getEnvironment();
//获取bean定义的注册类
BeanDefinitionRegistry registry = conditionContext.getRegistry();
//获得当前系统名
String property = environment.getProperty("os.name");
//包含Windows则说明是windows系统,返回true
if (property.contains("Windows")){
return true;
}
return false;
}
}
接着,创建LinuxCondition类:
public class LinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
if (property.contains("Linux")){
return true;
}
return false;
}
}
修改MyConfig:
@Configuration
public class MyConfig {
//只有一个类时,大括号可以省略
//如果WindowsCondition的实现方法返回true,则注入这个bean
@Conditional({WindowsCondition.class})
@Bean(name = "bill")
public Person person1(){
return new Person("Bill Gates",62);
}
//如果LinuxCondition的实现方法返回true,则注入这个bean
@Conditional({LinuxCondition.class})
@Bean("linus")
public Person person2(){
return new Person("Linus",48);
}
}
标注在方法上:
修改测试程序,开始测试:
public class ConditionalTest {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
@Test
public void test1(){
String osName = applicationContext.getEnvironment().getProperty("os.name");
System.out.println("当前系统为:" + osName);
Map<String, Person> map = applicationContext.getBeansOfType(Person.class);
System.out.println(map);
}
}
/**测试结果
当前系统为:Windows 10
{bill=Person{name='Bill Gates',age=62}}
*/
一个方法只能注入一个bean实例,所以@Conditional标注在方法上只能控制一个bean实例是否注入
标注在类上:
@Configuration
@Conditional({WindowsCondition.class})
public class MyConfig {
//只有一个类时,大括号可以省略
//如果WindowsCondition的实现方法返回true,则注入这个bean
@Bean(name = "bill")
public Person person1(){
return new Person("Bill Gates",62);
}
//如果LinuxCondition的实现方法返回true,则注入这个bean
@Bean("linus")
public Person person2(){
return new Person("Linus",48);
}
}
一个类中可以注入很多实例,@Conditional标注在类上就决定了一批bean是否注入。
二、Spring注解之@Conditional的更多相关文章
- Spring 注解驱动(二)Servlet 3.0 注解驱动在 Spring MVC 中的应用
Spring 注解驱动(二)Servlet 3.0 注解驱动在 Spring MVC 中的应用 Spring 系列目录(https://www.cnblogs.com/binarylei/p/1019 ...
- Spring 注解(二)注解工具类 AnnotationUtils 和 AnnotatedElementUtils
Spring 注解(二)注解工具类 AnnotationUtils 和 AnnotatedElementUtils Spring 系列目录(https://www.cnblogs.com/binary ...
- Spring Boot 二十个注解
Spring Boot 二十个注解 占据无力拥有的东西是一种悲哀. Cold on the outside passionate on the insede. 背景:Spring Boot 注解的强大 ...
- 【Spring注解驱动开发】二狗子让我给他讲讲@EnableAspectJAutoProxy注解
写在前面 最近,二狗子入职了新公司,新入职的那几天确实有点飘.不过慢慢的,他发现他身边的人各个身怀绝技啊,有Spring源码的贡献者,有Dubbo源码的贡献者,有MyBatis源码的贡献者,还有研究A ...
- Spring 注解(二)注解工具类
本文转载自Spring 注解(二)注解工具类 导语 首先回顾一下 AnnotationUtils 和 AnnotatedElementUtils 这两个注解工具类的用法: @Test @GetMapp ...
- Spring 注解驱动(一)基本使用规则
Spring 注解驱动(一)基本使用规则 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 一.基本使用 @Configur ...
- spring注解扫描组件注册
最近对单点系统进行微服务拆分,被各个springboot的组件注册搞得云里雾里的.(有的是通过springboot的自动配置进IOC容器的,有的是自己添加构造方法添加进IOC容器.)决定抽时间将spr ...
- Spring注解(生命周期)
对于上面的知识图解,需要一点一点的研究. 首先核心容器: 控制反转 和 依赖注入 创建工程: maven仓库搜索 spring context : 引入后 <!-- https://mvnre ...
- 006-Spring Boot自动配置-Condition、Conditional、Spring提供的Conditional自动配置
一.接口Condition.Conditional(原理) 主要提供一下方法 boolean matches(ConditionContext context, AnnotatedTypeMetada ...
随机推荐
- IT兄弟连 Java语法教程 流程控制语句 控制循环结构1
Java语言没有提供goto语句来控制程序的跳转,这种做法提高了程序流程控制的可读性,但降低了程序流程控制的灵活性.为了弥补这种不足,Java提供了continue和break来控制循环结构.除此之外 ...
- Java数组拷贝的五种方法
在Java中有多种方法可以拷贝一个数组,到另外一个数组. 1.循环拷贝 在循环拷贝方法中,只需要利用i,移动指针即可复制所有数组到arrayB中. for(int i=0;i<arrayA.le ...
- idea插件备份
- mosquitto配置文件
#配置文件为mosquitto #参见mosquitto.conf(5)了解更多信息. #显示默认值,取消注释以更改. #使用#字符来表示注释,但只有当它是 #第一个字符就行了. #========= ...
- python爬取昵称并保存为csv
代码: import sys import io import re sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030') ...
- C# ICloneable,shallow clone,deep clone.
[Serializable] public class Person:ICloneable { public string Name { get; set; } public int Id { get ...
- css文本超出部分用省略号表示
以前我在面试中遇到过这个问题,当时没答上来,现在回答一下: 1.设置三个属性: overflow:hidden (超出部分隐藏) white-space:nowrap (强制不换行) tex ...
- 用vue和layui简单写一个响应式数据展示表
在创建项目之前,先把我们需要的文件打包处理 <!DOCTYPE html> <html lang="en"> <head> <meta c ...
- 「SAP技术」 SAP MM MPN物料的采购初探
「SAP技术」 SAP MM MPN物料的采购初探 1, MPN物料号与我方正常使用料号物料主数据之间的LINK关系维护 MPN料号 14000005 , 我方料号11000250 , 2,采购信息记 ...
- 分布式文件管理系统HDFS
Hadoop 分布式文件管理系统HDFS可以部署在廉价硬件之上,能够高容错. 可靠地存储海量数据(可以达到TB甚至PB级),它还可以和Yam中的MapReduce 编程模型很好地结合,为应用程序提供高 ...