2011-03-31 99 views
0

我需要在运行时机会Spring bean属性值。目前我正在做这样春天设置抽象豆属性值

Object bean = context.getBean(beanName); 
BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(bean); 
wrapper.setPropertyValue(propertyName, newValue); 

但一些豆类配置为抽象

<bean id="abstractFoo" abstract="true" class="com.Foo" /> 

<bean id="bar" class="com.Bar"> 
    <constructor-arg><bean parent="abstractFoo" /></constructor-arg> 
</bean> 

,并在这种情况下context.getBean("abstractFoo")抛出BeanIsAbstractException

这真是简单的例子,但我希望你明白了。

任何想法如何更改抽象bean的属性值(在这种情况下'abstractFoo')? 我们正在使用弹簧2.5.4

编辑

改变一个XML例子更加具体。由于安全原因,abstractFoo被声明为抽象。

+2

您需要谨慎从bean定义中区分出一个bean。例如''does * not *表示一个bean,只是一个bean定义。所以你不能以这个名字来请求一个bean,但是没有这样的bean。 – skaffman 2011-03-31 10:30:03

回答

2

Spring应用程序上下文包含bean定义,Spring实例化由这些定义定义的bean对象。

您当前的代码将获得一个从命名bean定义创建的对象,并更改其属性。然而,bean永远不会被实例化为对象,它们仅以定义的形式存在,这些定义由具体bean的定义继承。

所以,如果你想改变抽象bean的属性,你需要改变它们的定义,这可以使用BeanFactoryPostProcessor来完成。但是,请注意,后置处理器在容器启动期间应用,因此如果您希望它实际上是“运行时”,则此方法不适用。

+0

是的,它必须完成“运行时”此事的整体思路是,支持可以改变配置参数,而无需事后重新启动应用程序。 – vrm 2011-03-31 10:46:29

+0

@vrm:我认为在运行时更改配置比简单修改bean属性更复杂。通常,您的对象应该设计为允许运行时配置更改。例如,您可以引入一个单独的配置持有者对象,并使您的对象从中检索配置属性。 – axtavt 2011-03-31 11:44:18

+0

好的,但不幸的是,为时已晚 – vrm 2011-03-31 13:08:45

0

声明:这是未经测试;离开我的头顶。不知道在启动阶段后它是否会工作。

您需要获取ConfigurableListableBeanFactory的实例。你的appcontext可能是一个,所以你可以投它。

从那里,获取bean定义并更改属性。

ConfigurableListableBeanFactory clbf = (ConfigurableListableBeanFactory)context; 
    BeanDefinition fooDefinition = clbf.getBeanDefinition("abstractFoo"); 
    MutablePropertyValues pv = fooDefinition.getPropertyValues(); 
    pv.add(propertyName, newValue); 

也许你需要重新注册你的BeanDefinition与之后的ConfigurableListableBeanFactory。我不是100%肯定的;你必须测试一下。

请记住,如果它有效,它将只适用于在发生更改后实例化的豆。