Spring为何依据方法名判定Bean是否跳过注册?能否优化该逻辑?
Spring Profile下同名Bean无法注册的问题分析与疑问
背景
我遇到如下代码:
public class TestClass { @Profile("profile") @Bean(name = "beanMethodName") //我知道这不是添加限定符的正确方式 public Function<String, String> beanMethodName(final String arg) { // 执行逻辑 } @Profile("!profile") @Bean(name = "beanMethodName") public Function<String, String> beanMethodName(final String arg1, final String arg2) { // 执行逻辑 } }
当以profile = test启动Spring应用时,beanMethodName Bean始终无法创建。
根因
该问题源于Spring判定Bean创建与跳过的逻辑,ConfigurationClassBeanDefinitionReader中存在如下代码块:
// 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; } if (configClass.skippedBeanMethods.contains(methodName)) { return; }
第一个方法的this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)返回TRUE(Profile不匹配),方法名被加入skippedBeanMethods;第二个方法的该判断返回FALSE,但因方法名已在skippedBeanMethods中,仍被跳过注册。
问题/疑问
当前逻辑迫使开发者为不同Profile的Bean使用不同方法名,即便它们是同一Bean的不同实现。虽有说法称调整Configuration中Bean定义顺序可解决,但换个Profile就会因顺序问题失效。
我提出如下修改方案:
// Do we need to mark the bean as skipped by its condition? boolean shouldSkip = this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN); if (configClass.skippedBeanMethods.contains(methodName) && shouldSkip) { return; } else if (shouldSkip) { configClass.skippedBeanMethods.add(methodName); return; }
该方案可将Bean Method Name与skippedBeanMethods判断解耦:
- 若方法名在
skippedBeanMethods中且shouldSkip(..)返回TRUE,则跳过Bean; - 若方法名不在
skippedBeanMethods中但shouldSkip(..)返回TRUE,则跳过并将方法名加入集合; - 其他情况允许注册,即仅当
shouldSkip(..)返回TRUE时才跳过Bean注册。
我知晓可通过修改方法名或使用合适的Qualifier解决该问题,但想了解:为何不能将Bean注册与方法名解耦?
内容的提问来源于stack exchange,提问作者Suyash Khandwe
相关产品推荐
相关产品推荐

