Spring3开始提供的profile机制用起来的确很爽,在Spring4中提供了一种更通用的条件化Bean定义机制。
@Conditional注解
使用@Conditional注解
定义一个Bean,这个Bean只有在满足MagicExistCondition中定义的条件时才会创建。
1 2 3 4 5
| @Bean @Conditional(MagicExistCondition.class) public MagicBean magicBean() { return new MagicBean(); }
|
这里的@Conditional注解定义如下:
1 2 3 4 5 6 7 8 9 10 11 12
| @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Conditional {
Class<? extends Condition>[] value();
}
|
实现Condition接口
1 2 3 4 5 6 7 8 9 10 11 12
| public class MagicExistCondition implements Condition {
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Environment env = context.getEnvironment(); return env.containsProperty("magic"); }
}
|
这里的matches方法有两个参数,分别为ConditionContext,AnnotatedTypeMetadata类型
ConditionContext
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
public interface ConditionContext {
BeanDefinitionRegistry getRegistry();
ConfigurableListableBeanFactory getBeanFactory();
Environment getEnvironment();
ResourceLoader getResourceLoader();
ClassLoader getClassLoader();
}
|
AnnotatedTypeMetadata
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public interface AnnotatedTypeMetadata {
boolean isAnnotated(String annotationName);
Map<String, Object> getAnnotationAttributes(String annotationName);
Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString); MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName); MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString);
}
|
Spring4对@Profile注解进行的重构
从Spring4开始,@Profile注解使用@Conditional注解实现。我们可以以它为例,学习如何使用@Conditional注解。
1 2 3 4 5 6 7 8 9 10 11
|
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented
@Conditional(ProfileCondition.class) public @interface Profile { String[] value(); }
|
可以看以下ProfileCondition的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
class ProfileCondition implements Condition {
@Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { if (context.getEnvironment() != null) { MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName()); if (attrs != null) { for (Object value : attrs.get("value")) { if (context.getEnvironment().acceptsProfiles(((String[]) value))) { return true; } } return false; } } return true; }
}
|
SpringBoot自动化配置中的Condition
Spring中的自动化配置基本就是靠这个@Condition注解实现的,所以在springboot-autoconfig中有一大堆实现了Condition接口的类:
另外SpringBoot还提供了很多类似于@Profile的注解:
如果有机会再后续的文章中会对SpringBoot的自动化配置进行详细分析。
参考:
Spring In Action
Spring Framework Documentation
本作品采用 知识共享署名 4.0 国际许可协议 进行许可。
转载时请注明原文链接:https://blog.hufeifei.cn/2018/02/J2EE/Spring%E9%AB%98%E7%BA%A7%E7%AF%87-@Conditional%E6%B3%A8%E8%A7%A3/