6

如何使用 java spring 在运行时动态更改 bean 的属性?我有一个 bean mainView,它应该使用“class1”或“class2”作为属性“class”。这个决定应该基于一个属性文件,其中属性“withSmartcard”是“Y”或“N”。

应用上下文:

<bean id="mainView"
    class="mainView">
    <property name="angebotsClient" ref="angebotsClient" />
    <property name="class" ref="class1" />
</bean>



<bean id="class1"
    class="class1">
    <constructor-arg ref="mainView" />
</bean>

<bean id="class2"
    class="class2">
    <constructor-arg ref="mainView" />
</bean>

属性文件:

withSmartcard=Y

4

5 回答 5

10

使用 PropertyPlaceHolder 管理您的属性文件..

<bean id="myPropertyPlaceHolder" 
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <description>The service properties file</description> 
  <property name="location" value="classpath:/some.where.MyApp.properties" /> 
  </bean>

并更改您的 ref 属性如下:

<bean id="mainView"
    class="mainView">
    <property name="angebotsClient" ref="angebotsClient" />
    <property name="class" ref="${withSmartCardClassImplementation}" />
</bean>

在您的属性文件 some.where.MyApp.properties 中,添加一个名为withSmartCardClassImplementation的键,该键将具有 class1 或 class2(您选择)作为值。

withSmartCardClassImplementation=class1
于 2009-04-28T13:27:55.780 回答
4

您需要PropertyPlaceholderConfigurer。手册的那部分比我在现场更好地展示了它。

在您的示例中,您需要将属性的值更改为class1class2(spring 上下文中所需 bean 的名称)。

或者,您的配置可能是:

<bean id="mainView"
    class="mainView">
    <property name="angebotsClient" ref="angebotsClient" />
    <property name="class">
        <bean class="${classToUse}">
            <constructor-arg ref="mainView"/>
        </bean>
    </property>
</bean>

配置文件包含:classToUse=fully.qualified.name.of.some.Class

在用户可编辑的配置文件中使用 bean 或类名是不可接受的,您确实需要使用“Y”和“N”作为配置参数值。在这种情况下,您只需要在 Java 中执行此操作,Spring 并不意味着是图灵完备的。

mainView 可以直接访问应用程序上下文:

if (this.withSmartCards) {
    this.class_ = context.getBean("class1");
} else {
    this.class_ = context.getBean("class2");
}

一个更干净的解决方案是将用户配置的处理封装在它自己的类中,这样可以减少需要 ApplicationContextAware 的类的数量,并根据需要将其注入到其他类中。

使用BeanFactoryPostProcessor,您可以通过编程方式注册类属性的定义。使用FactoryBean,您可以动态创建一个 bean。两者都是 Spring 的高级用法。

顺便说一句:鉴于 mainView 和 class1 / class2 之间的循环依赖关系,我不确定您的示例配置是否合法。

于 2009-04-28T13:55:34.060 回答
1

我相信您可以编写一个实现BeanFactoryPostProcessor的类。如果 XML 配置文件中存在此类的 bean(与您的其他 bean 一起),Spring 将自动调用其postProcessBeanFactory(ConfigurableListableBeanFactory)方法。传递给此方法的ConfigurableListableBeanFactory对象可用于在 Spring 开始初始化它们之前更改任何 bean 定义。

于 2009-04-28T13:29:43.420 回答
1

同意上面的@Olivier。

有很多方法可以做到这一点。

  1. 使用 PropertyPlaceHolderConfigurer..
  2. 使用 BeanPostProcessor..
  3. 使用 Spring AOP,创建建议并操作属性。

我会推荐上面的第 1 项。

于 2009-04-28T14:00:28.400 回答
1

使用类工厂。它可以根据您的属性返回实例。

于 2009-04-28T13:23:45.790 回答