dynamically change spring beans

2019-02-07 05:23发布

how do I dynamically change the properties of a bean at runtime using java spring? I have a bean mainView, which should use as property "class" either "class1" or "class2". This decision should be made on base of an property-file, where the property "withSmartcard" is "Y" or "N".

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:

withSmartcard=Y

5条回答
欢心
2楼-- · 2019-02-07 06:05

Agree with @Olivier above.

There are many ways to do it.

  1. Use PropertyPlaceHolderConfigurer..
  2. Use BeanPostProcessor..
  3. Use Spring AOP, create an advice and manipulate the properties.

I would recommend item no:1 above.

查看更多
Fickle 薄情
3楼-- · 2019-02-07 06:08

I believe you can write a class that implements 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. The ConfigurableListableBeanFactory object handed to this method can be used to change any bean definitions before Spring goes to work initializing them.

查看更多
爷的心禁止访问
4楼-- · 2019-02-07 06:14

You want the 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).

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

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. In that case, you'll just have to do this in Java, Spring isn't meant to be turing-complete.

mainView could access the application context directly:

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.

Using BeanFactoryPostProcessor, you could register a definition of the class property programmatically. Using FactoryBean, you can create a bean dynamically. Both are somewhat advanced usages of Spring.

An aside: I'm not sure if your example config is legal, given the cyclic dependency between mainView and class1 / class2.

查看更多
劳资没心,怎么记你
5楼-- · 2019-02-07 06:19

Use class factory. which can return instance on the basis of your property.

查看更多
Deceive 欺骗
6楼-- · 2019-02-07 06:22

Use a PropertyPlaceHolder to manage your properties file ..

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

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

withSmartCardClassImplementation=class1
查看更多
登录 后发表回答