Я хотел бы настроить Spring через XML так, чтобы, если конкретный бин существовал, он был внедрен в целевой бин. Если он не существует, будет добавлен другой компонент по умолчанию.
Например, если у меня есть такой файл
<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
использовался вместо бина defaultCar
. Моя первоначальная попытка не работает, но я думаю, иллюстрирует то, чего я пытаюсь достичь:
<bean id="carDriver" class="Driver">
<property name="car" value="#{ @customCar eq null ? 'defaultCar' : 'customCar' }"/>
</bean>
Я знаю, как это сделать с PropertyPlaceholderConfigurer
, но я не хочу указывать файл свойств / свойство VM / переменную среды / и т.д. в дополнение к файлу, содержащему пользовательский компонент. Спасибо!
Обновление:
Основываясь на комментариях «использовать фабричный бин», я изучил это и нашел следующее решение. Во-первых, я создал общий фабричный компонент, который позволяет вам указать имя компонента по умолчанию и переопределить имя компонента:
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, но это работает. Возможно, добавление пользовательского элемента схемы сделает этот процесс чище.
Дополнительные комментарии приветствуются.