我有两个xml文件定义了springframework(版本2.5.x)的bean:
containerBase.xml:
<beans>
<bean id="codebase" class="com.example.CodeBase">
<property name="sourceCodeLocations">
<list>
<value>src/handmade/productive</value>
</list>
</property>
</bean>
</beans>
...和
containerSpecial.xml:
<beans>
<import resource="containerBase.xml" />
</beans>
现在我想在sourceCodeLocations
中调整bean codebase
的属性containerSpecial.xml
。我需要添加第二个值src/generated/productive
。
一种简单的方法是覆盖codebase
中containerSpecial.xml
的定义,并添加两个值,即来自containerBase.xml
的值和新值:
containerSpecial.xml:
<beans>
<import resource="containerBase.xml" />
<bean id="codebase" class="com.example.CodeBase">
<property name="sourceCodeLocations">
<list>
<value>src/handmade/productive</value>
<value>src/generated/productive</value>
</list>
</property>
</bean>
</beans>
有没有办法扩展列表而不重新定义bean?
编辑2009-10-06:
这样做的目的是拥有一个由许多不同项目使用的共享标准容器containerBase
。每个项目都可以在自己的containerSpecial
中覆盖/扩展该项目特有的一些属性。如果项目未覆盖,则使用containerBase
中定义的默认值。
答案 0 :(得分:8)
在Spring容器实例化CodeBase bean之前,您可以使用BeanFactoryPostProcessor来更改bean的元数据。例如:
public class CodebaseOverrider implements BeanFactoryPostProcessor {
private List<String> sourceCodeLocations;
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
CodeBase codebase = (CodeBase)beanFactory.getBean("codebase");
if (sourceCodeLocations != null)
{
codebase.setSourceCodeLocations(sourceCodeLocations);
}
}
public void setSourceCodeLocations(List<String> sourceCodeLocations) {
this.sourceCodeLocations = sourceCodeLocations;
}
}
然后在contextSpecial.xml中:
<beans>
<import resource="context1.xml" />
<bean class="com.example.CodebaseOverrider">
<property name="sourceCodeLocations">
<list>
<value>src/handmade/productive</value>
<value>src/generated/productive</value>
</list>
</property>
</bean>
</beans>
答案 1 :(得分:3)
是。 bean定义可以具有引用父bean定义的“父”属性。新的“子”定义继承了父级的大多数属性,并且可以覆盖任何这些属性。
请参阅Bean Definition Inheritance
此外,您可以使用Collection Merging合并父和子bean定义中的列表属性定义。这样,您可以在父bean定义中指定一些列表项,并在子bean定义中为其添加更多项。
答案 2 :(得分:1)
3种方法:
简单:有两个列表defaultSourceCodeLocations和additionalSourceCodeLocations,并让您的访问者方法检查这两个(或组合它们)。我已经在一些框架中看到了这一点 - 填充了一个默认的处理程序列表,然后添加了其他用户创建的处理程序......
更复杂但保持原始类干净:然后您可以创建CodeBaseModifier类。这将有一个init方法来改变注入的bean实例。
<bean id="codebaseModifier" class="com.example.CodeBase" init-method="populateCodeBase">
<property name="sourceCodeLocations" ref="codebase"/>
<property name="additionalSourceCodeLocations">
<list>
<value>src/handmade/productive</value>
</list>
</property>
</bean>
如果你想让它变得非常通用,你可以制作一个通过反射来做到这一点的bean修饰符。如果使用这种方法,请注意订购。 CodeBase的依赖bean必须确保首先实例化该类(依赖于)
3 2的变体...而不是直接创建CodeBase类而是创建一个返回填充bean的工厂。然后可以使用类似于2的方式将此工厂配置为2.具有defaultSourceCodeLocations和additionalSourceCodeLocations
除非你需要很多可扩展的属性,否则我会选择选项1.
答案 3 :(得分:1)
有没有办法在手工定义属性或其他配置中的列表?
似乎应用配置和布线紧密耦合。根据我的经验,如果在Spring中很难做某事,可能会有一种更简单的方法。
答案 4 :(得分:1)
在Spring 3.0中,您可以指定merge =&#34; true&#34;在&#39;列表&#39;标签。有关详细信息,请参阅http://forum.springsource.org/archive/index.php/t-97501.html。