Есть ли способ повторно использовать <util: list> в файле конфигурации Spring?
У меня есть набор правил, которые нужно внедрить в набор классов, как показано ниже:
<bean id="rule1" class="com.vikdor.rules.Rule1" />
<bean id="rule2" class="com.vikdor.rules.Rule2" />
<bean id="rule3" class="com.vikdor.rules.Rule3" />
<bean id="rule4" class="com.vikdor.rules.Rule4" />
<bean id="rule5" class="com.vikdor.rules.Rule5" />
<util:list id="commonRules">
<ref bean="rule1" />
<ref bean="rule3" />
<ref bean="rule5" />
</util:list>
<util:list id="normalInvRules">
<!-- Include common rules -->
<ref bean="rule4" />
</util:list>
<util:list id="prepaidInvRules">
<!-- Include common rules -->
<ref bean="rule2" />
</util:list>
Как я могу включить список общих правил в списки, соответствующие normalInvRules
а также prepaidInvRules
?
Количество правил (например, rule1, rule2 и т. Д.) Больше, а количество групп (normalInvRules, prepidInvRules и т. Д.) Также больше. Итак, мне интересно, есть ли способ избежать повторения общих правил и просто перечислить только конкретные и включить ссылку на общий список.
4 ответа
Существует функция, называемая "слияние коллекций", которая делает именно это. Смотрите раздел 3.3.3.4.1. "Слияние коллекций" в документации Spring или в блоге 2008 года (с примером), который я написал на эту тему.
Мне нравится подход, предложенный @GreyBeardedGeek, просто хочу добавить еще несколько предложений:
а. Делать это с помощью @Configuration
со списком базовых правил в xml:
@Configuration
@ImportResource("classpath:/baseconfig.xml")
public static class RulesConfiguration{
@Resource List<Rule> commonRules;
@Bean
public List<Rule> normalInvRules(){
List<Rule> rules = new ArrayList<Rule>();
rules.addAll(commonRules);
rules.add(new Rule());
return rules;
}
}
б. Использование пользовательского фабричного компонента, отвечающего за расширение списка:
class ListExpandingFactoryBean<T> implements FactoryBean<List<T>>{
private List<T> baseList;
private List<T> extendedList;
@Override
public List<T> getObject() throws Exception {
List<T> consolidatedList = new ArrayList<T>();
consolidatedList.addAll(baseList);
consolidatedList.addAll(extendedList);
return consolidatedList;
}
@Override
public Class<?> getObjectType() {
return List.class;
}
@Override
public boolean isSingleton() {
return false;
}
public void setBaseList(List<T> baseList) {
this.baseList = baseList;
}
public List<T> getExtendedList() {
return extendedList;
}
public void setExtendedList(List<T> extendedList) {
this.extendedList = extendedList;
}
}
и используя это так:
<bean name="normalInvRules" class="ListExpandingFactoryBean" p:baseList-ref="commonRules">
<property name="extendedList">
<list>
<ref bean="bean4"/>
</list>
</property>
</bean>
Спасибо за ответы. Вот как я, наконец, обратился к этому, используя Collection Merging
:
<bean id="rule1" class="com.krovi.rules.Rule1" />
<bean id="rule2" class="com.krovi.rules.Rule2" />
<bean id="rule3" class="com.krovi.rules.Rule3" />
<bean id="rule4" class="com.krovi.rules.Rule4" />
<bean id="rule5" class="com.krovi.rules.Rule5" />
<bean id="commonList"
class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list>
<ref bean="rule1" />
<ref bean="rule2" />
<ref bean="rule3" />
</list>
</property>
</bean>
<bean id="firstExecutorRules" parent="commonList"
class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list merge="true">
<ref bean="rule4" />
</list>
</property>
</bean>
<bean id="secondExecutorRules" parent="commonList"
class="org.springframework.beans.factory.config.ListFactoryBean">
<property name="sourceList">
<list merge="true">
<ref bean="rule5" />
</list>
</property>
</bean>
Вы можете создать класс с общими правилами и автоматически связать их с другими правилами? Разве это не сработает?
Вы можете использовать тот же подход, используя конфигурацию XML, и внедрить его, используя атрибут ref.