条件注解@Conditional
简介
在学习SpringBoot的时候我们会在各种⾃动配置类中看到⼤量使⽤了@Conditional注解,这篇⽂章主要简单说下@Conditional注解的使⽤⽅法。
定义:
按照《Spring Boot实战》书中所说的:“@Conditional根据满⾜某⼀特定条件创建⼀个特定的Bean。⽐⽅说,当某⼀个jar包在⼀个类路径下的时候,⾃动配置⼀个或多个Bean;或者只有某个Bean被创建才会才会创建另外⼀个Bean。总的来说,就是根据特定判定条件来控制Bean的创建⾏为,这样我们可以利⽤这个特性进⾏⼀些⾃动的配置。”
在使⽤该注解之前我们来看⼀下@Conditional的源码
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<?extends Condition>[]value();
}
我们关注下⾯的两点:
@Target({ElementType.TYPE, ElementType.METHOD}):表⽰该注解可以加在类上,表⽰该类下⾯的所有@Bean都会启⽤配置;
也可以加在⽅法上,只对该⽅法有效
Class<? extends Condition>[] value():表⽰要传⼀个Class集合给该注解,即@Conditional({XXX.class,XXX.class}) ,⽽且XXX类要继承Condition接⼝。关于Condition下⾯会说。
⽰例
我们以⾃⼰电脑的操作系统为判定条件,若我们的操作系统为Linux则创建Linux之⽗的Person的Bean;若操作系统为Windows则创建Windows之⽗的Person的Bean。
⼀、⾸先我们来创建⼀个Person类:
/**
* Created on 2020/3/31
gwd
* Package com.study.spring.annotation.bean *
* @author dsy
*/
public class Person {
private String name;
private Integer age;
public Person(){
}
楚门的世界英文影评
public Person(String name, Integer age){
this.name = name;
this.age = age;
}
public String getName(){
vince gill
return name;
}
public void tName(String name){
this.name = name;
}
public Integer getAge(){
return age;
}
public void tAge(Integer age){
this.age = age;
}
@Override
public String toString(){
return"Person{"+
"name='"+ name +'\''+
", age="+ age +
'}';
}
}
⼆、再创建⼀个配置类MyConfig:
import com.study.spring.annotation.bean.Person;
import com.study.dition.LinuxCondition;
import com.study.dition.WindowsCondition;
import t.annotation.*;
/**
* Created on 2020/3/31
* Package com.study.fig
*
* @author dsy
*/
@Configuration//标识该类是⼀个配置类,相当于之前的⼀个xml配置⽂件
public class MyConfig {
/**
* @Conditional({Condition}) 注解:按照⼀定的条件将bean添加到IOC容器中
*/
@Conditional({LinuxCondition.class})
@Bean("linux")
public Person person01(){
return new Person("linux之⽗",55);
}
@Bean("windows")
@Conditional({WindowsCondition.class})
public Person person02(){
nowhere
return new Person("windows之⽗",48);
}
}
三、接下来创建两个Condition类:LinuxCondition和WindowsCondition:
package com.study.dition;
import t.annotation.Condition;
import t.annotation.ConditionContext;
import nv.Environment;
import ype.AnnotatedTypeMetadata;
/**
* Created on 2020/3/31
* Package com.study.dition
*
* @author dsy
*/
//判断是否Linux系统要进⾏判断必须实现Condition接⼝
public class LinuxCondition implements Condition {
/**
ogc是什么意思*
* @param conditionContext 判断条件能使⽤的上下⽂环境
* @param annotatedTypeMetadata 当前标注了@Conditional注解的注释信息
* @return Boolean
*/
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata){ Environment environment = Environment();
String property = Property("os.name");
return property!=null&&ains("Linux");
}
}
import org.springframework.fig.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import t.annotation.Condition;
import t.annotation.ConditionContext;
import nv.Environment;
import ype.AnnotatedTypeMetadata;
/**
* Created on 2020/3/31
* Package com.study.dition
*
* @author dsy
*/
//判断是否Windows系统要进⾏判断必须实现Condition接⼝
public class WindowsCondition implements Condition {
/**
lead in
*
* @param conditionContext 判断条件能使⽤的上下⽂环境
* @param annotatedTypeMetadata 当前标注了@Conditional注解的注释信息
* @return Boolean
*/
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata){
Environment environment = Environment();
String property = Property("os.name");
return property != null && ains("Windows");
}
singlish}
说明: 这两个类均实现了Condition接⼝,⾥⾯只有⼀个matches⽅法返回值为boolea类型,也就是说
@Conditional({LinuxCondition.class})或者@Conditional({WindowsCondition.class})通过判断注解括号⾥⾯条件类的matches⽅法的返回值来判定要不要在IOC容器中创建由@Conditional注解标识的这个Bean;若matches返回值为true则创建该Bean,若返回fal则不创建该Bean。
@FunctionalInterface
public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}
四、测试:
package com.study.spring;
import com.study.spring.annotation.bean.Person;
import com.study.fig.MyConfig;
import org.junit.jupiter.api.Test;
import org.st.context.SpringBootTest;
import t.annotation.AnnotationConfigApplicationContext;
import java.util.Map;
@SpringBootTest
class ApplicationTests {
/
**
* @Conditional 注解来按照条件获取bean实例
*/
@Test
void testAnnotationConfig2(){
//创建IOC容器
AnnotationConfigApplicationContext applicationContext =new AnnotationConfigApplicationContext(MyConfig.class);
//getBeanNamesForType⽅法按照类来获取该类的Bean的id
google英文版String[] names = BeanNamesForType(Person.class);
//打印
apologi
for(String name:names){
suchas
System.out.println(name);
}
//获取具体的Bean
Map<String, Person> beans = BeansOfType(Person.class);
System.out.println(beans);
}
}
打印输出:
windows
{windows=Person{name='windows之⽗', age=48}}
若我们改变运⾏环境,加上参数:-Dos.name=Linux
再次运⾏打印输出:
linux
{linux=Person{name='linux之⽗', age=55}}
总结
1、@Conditional注解的作⽤是按照⼀定的判定条件来控制Bean的创建
2、@Conditional可以加在⼀个配置类上,表⽰该类下⾯的全部的@Bean都会启⽤配置;也可以加在⼀个@Bean的⽅法上⾯,只对该⽅法有效
3、判定条件类XXXCondition类要实现Condition接⼝,并重写matches⽅法,在该⽅法⾥⾯写⾃⼰的判定逻辑
参考资料:《Spring Boot实战》