源码解析
-
这个注解可以用来创建条件,来决定在什么情况下创建哪些bean对象
-
首先看源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value();
}
-
从源码可以看出来,这个注解有一个value属性,该属性返回的是一个继承了Condition接口的一个类所构成的一个数组。
-
看一下Condition接口是一个什么样的接口,上源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.context.annotation;
import org.springframework.core.type.AnnotatedTypeMetadata;
public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}
-
可以看到,Condition接口中有一个方法matches,该方法的返回值是一个boolean值。因为Condition本来就是用来构造条件的,所以说满足条件的话就返回true,不满足条件的话就返回flase。
-
matches方法有两个参数,一个是ConditionContext类型的,另一个是AnnotatedTypeMetadata类型的。
-
ConditionContext,是判断条件使用的上下文
-
AnnotatedTypeMetadata,是注释信息
①
-
ConditionContext是一个接口,里面有五个get方法,对应五种返回值,分别能够得到
package org.springframework.context.annotation;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
public interface ConditionContext {
//借助getRegistry()返回的BeanDefinitionRegistry可以检查bean定义
BeanDefinitionRegistry getRegistry();
//借助getBeanFactory()返回的ConfigurableListableBeanFactory检查bean是否存在,甚至探查bean的属性
ConfigurableListableBeanFactory getBeanFactory();
//借助getEnvironment()返回的Environment检查环境变量是否存在以及它的值是什么
Environment getEnvironment();
//借助getResourceLoader()返回的ResourceLoader所加载的资源
ResourceLoader getResourceLoader();
//借助getClassLoader()返回的ClassLoader加载并检查类是否存在
ClassLoader getClassLoader();
}
②
-
matches方法的第二个参数是AnnotatedTypeMetadata类型的
-
看一下源码:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.core.type;
import java.util.Map;
import org.springframework.util.MultiValueMap;
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);
}
-
具体使用:
-
当我们想要自己构造田间决定创建哪些bean对象的时候,可以new一个class,这个class实现Conditional接口,覆写matches方法。这个class的作用就是构造条件。
-
当matches方法返回true,按照所构造的条件来决定创建哪些bean。
-
当matches方法返回flase,不按照所构造的条件来决定创建哪些bean。
例子
-
根据环境是Linux还是Windows来决定加载哪些bean
以下的两个class都实现了Condition类 使用ConditionContext参数获取到了当前程序运行的环境是linux还是Windows 返回true或flase
package cr.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* @Author cr
* @Date 2022/10/7 19:20
*/
public class MacConditional implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//获取运行环境
Environment environment = conditionContext.getEnvironment();
String osName = environment.getProperty("os.name");
if (osName.contains("Mac")){
return true;
}
return false;
}
}
package cr.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* @Author cr
* @Date 2022/10/7 19:26
*/
public class WindowsConditional implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String osName = environment.getProperty("os.name");
if (osName.contains("Windows")){
return true;
}
return false;
}
}
-
在注入bean的类中,在@Bean修饰的方法头上,加上注释@Conditional。并且该注释的属性的返回值是一个类(该类继承于Condition,也就是以上的两个class)
@Configuration
public class MainConfig2 {
//如果为Windows环境则创建windows对象
@Conditional({WindowsConditional.class})
@Bean("windows")
public Person getBill() {
return new Person("windows操作系统",40) ;
}
//如果为Mac环境则创建mac对象
@Conditional({MacConditional.class})
@Bean("mac")
public Person getlinux() {
return new Person("mac",45) ;
}
}
来源:blbl雷丰阳Spring讲解