条件化的Bean——@Conditional注解
条件化的Bean——@Conditional注解
当我们希望某个Bean满⾜了⼀定的条件才会被创建的时候,我们就可以使⽤@Conditional注解(Spring 4引⼊)来实现这种功能。
北宋五子该注解可以⽤到带有@Bean注解的⽅法上,如果给定的条件计算结果为true,就会创建这个bean,否则的话,这个bean会被忽略。常见条件注解
1. @ConditionalOnBean(仅仅在当前上下⽂中存在某个对象时,才会实例化⼀个Bean)
2. @ConditionalOnClass(某个class位于类路径上,才会实例化⼀个Bean)
3. @ConditionalOnExpression(当表达式为true的时候,才会实例化⼀个Bean)
4. @ConditionalOnMissingBean(仅仅在当前上下⽂中不存在某个对象时,才会实例化⼀个Bean)
5. @ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化⼀个Bean)
6. @ConditionalOnNotWebApplication(不是web应⽤)
⾃定义条件
假设有⼀个名为MagicBean的类,我们希望只有设置了magic环境属性的时候,Spring才会实例化这个类。
条件化地配置bean
@Bean
@Conditional(MagicExistsCondition.class)
public MagicBean magicBean() {消防检查
return new MagicBean();
中式牛排}
检查是否存在magic属性
package com.zheng.spring;
import t.annotation.Condition;
import t.annotation.ConditionContext;
一衣带水造句import nv.Environment;
import ype.AnnotatedTypeMetadata;
public class MagicExistsCondition implements Condition {
你画我猜的词语@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment env = Environment();
ainsProperty("magic"); // 检查magic属性
}
}
matches()⽅法通过给定的ConditionContext对象进⽽得到Environment对象,并使这个对象检查环境中是否存在名为magic的环境属性。
其中ConditionContext是⼀个接⼝
public interface ConditionContext {
BeanDefinitionRegistry getRegistry();
ConfigurableListableBeanFactory getBeanFactory();
Environment getEnvironment();小蚂蚁作文
ResourceLoader getResourceLoader();
ClassLoader getClassLoader();
}
借助getRegistry()返回的BeanDefinitionRegistry检查bean定义;
借助getBeanFactory()返回的ConfigurableListableBeanFactory检查bean是否存在,甚⾄探查bean的属性;
借助getEnvironment()返回的Environment检查环境变量是否存在以及它的值是什么;
读取并探查getResourceLoader()返回的ResourceLoader所加载的资源;
借助getClassLoader()返回的ClassLoader加载并检查类是否存在。
AnnotatedTypeMetadata则能够让我们检查带有@Bean注解的⽅法上还有什么其他的注解。像ConditionContext⼀
样,AnnotatedTypeMetadata也是⼀个接⼝。
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);
}
借助isAnnotated()⽅法,我们能够判断带有@Bean注解的⽅法是不是还有其他特定的注解。借助其他的那些⽅法,我们能够检查@Bean注解的⽅法上其他注解的属性。
@Profile注解与条件化的关系
从Spring 4开始,@Profile注解基于@Conditional和Condition实现。
下⾯是@Profile实现的源码
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
眸的读音
public @interface Profile {
/**
* The t of profiles for which the annotated component should be registered.
*/
String[] value();
}
其中ProfileCondition检查某个bean profile是否可⽤,源码如下
class ProfileCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
if (Environment() != null) {
MultiValueMap<String, Object> attrs = AllAnnotationAttributes(Name());
if (attrs != null) {
for (Object value : ("value")) {
if (Environment().acceptsProfiles(((String[]) value))) {
return true;
}
}
return fal;
}
瑕不掩瑜什么意思}
return true;
}
}
ProfileCondition通过AnnotatedTypeMetadata得到了⽤于@Profile注解的所有属性。借助该信息,它会明确地检查value属性,该属性包含了bean的profile名称。然后,它根据通过ConditionContext得到的Environment来检查[借助acceptsProfiles()⽅法]该profile是否处于激活状态。如果是则选择这个profile bean进⾏创建。