Spring 多個Conditional -> Bean建立
阿新 • • 發佈:2019-01-02
@Bean
@ConditionalOnBean(DataSource.class) // 1
@ConditionalOnProperty("xxx") //2
public String hello(){
System.out.println(">>>>>>>>>>>>>>>> init..... Hello world");
return "Hello World";
}
考慮一個問題?
在這個裡面,滿足什麼條件才會建立hello這個Bean
- 猜想1:滿足條件1或條件2
- 猜想2:滿足條件1和條件2
- 猜想3:無需滿足任何條件
顯然 猜想3 是錯誤的
… 十秒鐘之後
經過試驗,
猜想2正確.
那麼是為什麼呢?
首先這個在@Configuration
裡面,那麼入口應該是,解析Configuration
這個類ConfigurationClassPostProcessor
然後它是藉助ConfigurationClassBeanDefinitionReader
這個類解析Configuration
的
然後在這個類的loadBeanDefinitionsForBeanMethod()
方法中,這麼一個判斷條件
// Do we need to mark the bean as skipped by its condition?
if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
configClass.skippedBeanMethods.add(methodName);
return;
}
沒錯,看到了我們的Condition
然後點選進去 可以進入到ConditionEvalutor
這個類裡面
/**
* Determine if an item should be skipped based on {@code @Conditional } annotations.
* @param metadata the meta data
* @param phase the phase of the call
* @return if the item should be skipped
*/
public boolean shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationPhase phase) {
// 如果沒有註解或者註解中沒有Conditional這種註解
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;
}
if (phase == null) {
if (metadata instanceof AnnotationMetadata &&
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
}
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
List<Condition> conditions = new ArrayList<Condition>();
// 獲取所有的condition
for (String[] conditionClasses : getConditionClasses(metadata)) {
for (String conditionClass : conditionClasses) {
Condition condition = getCondition(conditionClass, this.context.getClassLoader());
conditions.add(condition);
}
}
// 排序,需實現Order介面
AnnotationAwareOrderComparator.sort(conditions);
for (Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
if (requiredPhase == null || requiredPhase == phase) {
// 只要有一個不符合,就跳過建立
if (!condition.matches(this.context, metadata)) {
return true;
}
}
}
return false;
}
所以可以看到,需要符合所有的Condition
才可以成功建立Bean