【发布时间】:2011-07-24 21:36:04
【问题描述】:
我想通过 XML 配置 Spring,如果存在特定的 bean,它将被注入目标 bean。如果它不存在,将注入一个不同的默认 bean。
例如,如果我有这样的文件
<bean id="carDriver" class="Driver">
<property name="car" value="SOME EXPRESSION GOES HERE, SEE ATTEMPT BELOW"/>
</bean>
<bead id="defaultCar" class="Car">
<property name="name" value="Honda Accord"/>
</bean>
然后加载它,我想将defaultCar 注入驱动程序。但是,如果我还加载以下文件:
<bean id="customCar" class="FlyingCar">
<property name="name" value="Rocket Car"/>
<property name="maxAltitude" value="80000"/>
</bean>
我希望使用 customCar bean 而不是 defaultCar bean。我最初的尝试不起作用,但我认为说明了我想要实现的目标:
<bean id="carDriver" class="Driver">
<property name="car" value="#{ @customCar eq null ? 'defaultCar' : 'customCar' }"/>
</bean>
我知道如何使用PropertyPlaceholderConfigurer 执行此操作,但除了包含自定义 bean 的文件之外,我不想提供属性文件/VM 属性/环境变量等。谢谢!
更新:
基于“使用工厂 bean”cmets,我对此进行了研究并提出了以下解决方案。首先,我创建了一个通用工厂 bean,它允许您指定默认 bean 名称和覆盖 bean 名称:
public class DefaultOverrideFactoryBean implements FactoryBean, BeanFactoryAware {
public Object getObject() throws Exception {
return beanFactory.containsBean(overrideBeanName) ?
beanFactory.getBean(overrideBeanName) :
beanFactory.getBean(defaultBeanName);
}
public Class<?> getObjectType() {
return Object.class;
}
public boolean isSingleton() {
return true;
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public void setDefaultBeanName(String defaultBeanName) {
this.defaultBeanName = defaultBeanName;
}
public void setOverrideBeanName(String overrideBeanName) {
this.overrideBeanName = overrideBeanName;
}
private String defaultBeanName;
private String overrideBeanName;
private BeanFactory beanFactory;
}
要配置我的示例汽车司机,您可以这样做:
<bean id="carDriver" class="Driver">
<property name="car">
<bean class="DefaultOverrideFactoryBean">
<property name="defaultBeanName" value="defaultCar"/>
<property name="overrideBeanName" value="customCar"/>
</bean>
</property>
</bean>
我更喜欢使用 SpEL,但这很有效。或许添加一个自定义架构元素会更简洁。
感谢其他 cmets。
【问题讨论】:
-
为什么不创建 FactoryCar bean。然后在您的 carDriver 中引用该工厂。