在父上下文中,我有如下属性声明:
<bean id="my.properties"
class="com.rcslabs.webcall.server.property.PropertyPaceholderConfigurer">
<property name="locations" value="classpath:/my.properties"/>
</bean>
在运行时之后,我需要创建一个子上下文,并使用运行时数据覆盖这些属性。最好的方法是什么?
此外:
更确切地说,我在运行时手动创建子上下文,如下所示:
ClassPathXmlApplicationContext childAppContext = new ClassPathXmlApplicationContext(parentApplicationContext);
那么,我可以在childAppContext中声明一个bean,就像通常使用BeanDefinitionRegistry一样吗?
答案 0 :(得分:1)
看起来你有一个PropertyPlaceholderConfigurer的子类,为什么不用逻辑检查运行时值来覆盖resolveProperty
,否则又回到默认值?您可能必须为子上下文创建一个专用子类,并在其中注入运行时值源。
您还可以执行的操作是将运行时值放在系统属性中,并使用覆盖模式systemPropertiesMode
。这是一个简单但不太干净的解决方案,我的第一种方法的一些变化会更好。如果您创建多个客户端上下文,只要您不并行生成它们,它就会起作用。
更新:我会从以下内容开始:
final Map<String,String> myRuntimeValues;
ClassPathXmlApplicationContext childAppContext = new ClassPathXmlApplicationContext(parentApplicationContext) {
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.prepareBeanFactory();
beanFactory.registerSingleton("myRuntimeValues", myRuntimeValues);
}
};
并将“myRuntimeValues”注入到客户端上下文文件中定义的PropertyPlaceholderConfigurer bean中。更多的挖掘可能会产生更好的解决方案,这不是一个典型的用例,我相信你会更进一步。
答案 1 :(得分:0)
在阐述mrembisz的答案时,这里是动态地将属性注入spring上下文的完整示例,无需在子xml中对任何bean进行硬编码,然后从父上下文传递bean引用。以下解决方案不需要为此目的定义父上下文。
public static void main(String args[]) {
AbstractApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] { "classpath:spring-beans.xml" }) {
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.prepareBeanFactory(beanFactory);
ArrayList<Properties> prList = new ArrayList<Properties>();
Properties pr = new Properties();
pr.setProperty("name", "MyName");
prList.add(pr);
Properties prArray[] = new Properties[prList.size()];
PropertySourcesPlaceholderConfigurer pConfig = new PropertySourcesPlaceholderConfigurer();
pConfig.setPropertiesArray(prList.toArray(prArray));
beanFactory.registerSingleton("pConfig", pConfig);
}
};
appContext.refresh();
System.out.println(appContext.getBean("name"));
}