简体   繁体   English

动态改变春豆

[英]dynamically change spring beans

how do I dynamically change the properties of a bean at runtime using java spring? 如何使用java spring在运行时动态更改bean的属性? I have a bean mainView, which should use as property "class" either "class1" or "class2". 我有一个bean mainView,它应该用作属性“class”“class1”或“class2”。 This decision should be made on base of an property-file, where the property "withSmartcard" is "Y" or "N". 此决定应基于属性文件进行,其中属性“withSmartcard”为“Y”或“N”。

ApplicationContext: ApplicationContext的:

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

PropertyFile: PropertyFile:

withSmartcard=Y withSmartcard = Y

Use a PropertyPlaceHolder to manage your properties file .. 使用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>

and change your ref attribute as follow : 并更改您的ref属性如下:

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

In your properties file some.where.MyApp.properties, add a key named withSmartCardClassImplementation which will have class1 or class2 (you choose) for value. 在属性文件some.where.MyApp.properties中,添加一个名为withSmartCardClassImplementation的键,它将具有class1或class2(您选择)作为值。

withSmartCardClassImplementation=class1

You want the PropertyPlaceholderConfigurer . 你想要PropertyPlaceholderConfigurer That section of the manual demonstrates it better than I could on the spot. 手册的这一部分比现场更好地展示了它。

In your example, you'd need to either to change the value of the property to class1 or class2 (the name of the desired bean in the spring context). 在您的示例中,您需要将属性的值更改为class1class2 (spring上下文中所需bean的名称)。

Alternately, your configuration could be: 或者,您的配置可能是:

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

with the configuration file containing: classToUse=fully.qualified.name.of.some.Class 配置文件包含:classToUse = fully.qualified.name.of.some.Class

Using bean or class names would not be acceptable in a user-editable configuration file, and you really need to use "Y" and "N" as the configuration parameter values. 在用户可编辑的配置文件中使用bean或类名是不可接受的,并且您确实需要使用“Y”和“N”作为配置参数值。 In that case, you'll just have to do this in Java, Spring isn't meant to be turing-complete. 在这种情况下,你只需要在Java中执行此操作,Spring并不意味着完成。

mainView could access the application context directly: mainView可以直接访问应用程序上下文:

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

A cleaner solution would be encapsulating processing of the user configuration in its own class that would do the above to reduce the number of classes that need to be ApplicationContextAware and inject it into your other classes as needed. 一个更干净的解决方案是将用户配置的处理封装在它自己的类中,该类将执行上述操作以减少需要为ApplicationContextAware的类的数量,并根据需要将其注入到其他类中。

Using BeanFactoryPostProcessor , you could register a definition of the class property programmatically. 使用BeanFactoryPostProcessor ,您可以以编程方式注册类属性的定义。 Using FactoryBean , you can create a bean dynamically. 使用FactoryBean ,您可以动态创建bean。 Both are somewhat advanced usages of Spring. 两者都是Spring的一些先进用法。

An aside: I'm not sure if your example config is legal, given the cyclic dependency between mainView and class1 / class2. 旁白:鉴于mainView和class1 / class2之间存在循环依赖关系,我不确定您的示例配置是否合法。

Use class factory. 使用班级工厂。 which can return instance on the basis of your property. 可以根据您的财产返回实例。

I believe you can write a class that implements BeanFactoryPostProcessor . 我相信你可以写一个实现BeanFactoryPostProcessor的类。 If a bean of this class exists in the XML configuration file (alongside your other beans), Spring will automatically call its postProcessBeanFactory(ConfigurableListableBeanFactory) method. 如果XML配置文件中存在此类的bean(与其他bean一起),Spring将自动调用其postProcessBeanFactory(ConfigurableListableBeanFactory)方法。 The ConfigurableListableBeanFactory object handed to this method can be used to change any bean definitions before Spring goes to work initializing them. 传递给此方法的ConfigurableListableBeanFactory对象可用于在Spring开始工作之前更改任何bean定义。

Agree with @Olivier above. 同意上面的@Olivier。

There are many ways to do it. 有很多方法可以做到这一点。

  1. Use PropertyPlaceHolderConfigurer.. 使用PropertyPlaceHolderConfigurer ..
  2. Use BeanPostProcessor.. 使用BeanPostProcessor ..
  3. Use Spring AOP, create an advice and manipulate the properties. 使用Spring AOP,创建建议并操纵属性。

I would recommend item no:1 above. 我建议上面的项目编号:1。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM