【问题标题】:dynamically change spring beans动态改变spring bean
【发布时间】:2010-10-22 07:47:47
【问题描述】:

如何使用 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

【问题讨论】:

    标签: java spring javabeans


    【解决方案1】:

    使用 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
    

    【讨论】:

    • 应该是 {$classIdToBeUsed} 还是 ${classIdToBeUsed}?
    • ${classIdToBeUsed} :) 错字,谢谢!显然,我将 classIdToBeUsed 更改为 withSmartCardClassImplementation
    【解决方案2】:

    你想要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 之间的循环依赖关系,我不确定您的示例配置是否合法。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

          同意上面的@Olivier。

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

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

          我会推荐上面的第 1 项。

          【讨论】:

            猜你喜欢
            • 2012-08-18
            • 2017-02-27
            • 2012-06-04
            • 2012-11-10
            • 1970-01-01
            • 1970-01-01
            • 2011-01-05
            • 1970-01-01
            • 2023-03-23
            相关资源
            最近更新 更多