java 动态更改 spring bean

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/797894/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 13:51:03  来源:igfitidea点击:

dynamically change spring beans

javaspringjavabeans

提问by ddejmek

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

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

withSmartcard=Y

回答by Olivier

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 withSmartCardClassImplementationwhich will have class1 or class2 (you choose) for value.

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

withSmartCardClassImplementation=class1

回答by millimoose

You want the PropertyPlaceholderConfigurer. That section of the manual demonstrates it better than I could on the spot.

您需要PropertyPlaceholderConfigurer。手册的那部分比我在现场表现得更好。

In your example, you'd need to either to change the value of the property to class1or 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. In that case, you'll just have to do this in Java, Spring isn't meant to be turing-complete.

在用户可编辑的配置文件中使用 bean 或类名称是不可接受的,您确实需要使用“Y”和“N”作为配置参数值。在这种情况下,您只需要在 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. Using FactoryBean, you can create a bean dynamically. Both are somewhat advanced usages of Spring.

使用BeanFactoryPostProcessor,您可以以编程方式注册类属性的定义。使用FactoryBean,您可以动态创建 bean。两者都是 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 之间的循环依赖关系,我不确定您的示例配置是否合法。

回答by Satya

Agree with @Olivier above.

同意上面的@Olivier。

There are many ways to do it.

有很多方法可以做到。

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

I would recommend item no:1 above.

我会推荐上面的第 1 项。

回答by dadua

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

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

回答by Adam Paynter

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 ConfigurableListableBeanFactoryobject handed to this method can be used to change any bean definitions before Spring goes to work initializing them.

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