我可以在运行时替换Spring bean定义吗?

Phi*_*das 68 java spring

请考虑以下情形.我有一个带有bean的Spring应用程序上下文,其属性应该是可配置的,思考DataSourceMailSender.可变应用程序配置由一个单独的bean管理,让我们调用它configuration.

管理员现在可以更改配置值,如电子邮件地址或数据库URL,我想在运行时重新初始化配置的bean.

假设我不能简单地修改上面的可配置bean的属性(例如由FactoryBean或者构造函数注入创建),但必须重新创建bean本身.

有关如何实现这一点的任何想法?我很高兴收到有关如何组织整个配置的建议.没有什么是固定的.:-)

编辑

为了澄清一点:我不是问如何更新配置或如何注入静态配置值.我会尝试一个例子:

<beans>
    <util:map id="configuration">
        <!-- initial configuration -->
    </util:map>

    <bean id="constructorInjectedBean" class="Foo">
        <constructor-arg value="#{configuration['foobar']}" />
    </bean>

    <bean id="configurationService" class="ConfigurationService">
        <property name="configuration" ref="configuration" />
    </bean>
</beans>
Run Code Online (Sandbox Code Playgroud)

所以有一个constructorInjectedBean使用构造函数注入的bean .想象一下,bean的构造非常昂贵,因此使用原型范围或工厂代理不是一种选择DataSource.

我想要做的是每次更新配置时(通过configurationServicebean constructorInjectedBean重新创建并重新注入应用程序上下文和依赖bean).

我们可以放心地假设constructorInjectedBean正在使用接口,因此代理魔术确实是一种选择.

我希望能让这个问题更清楚一些.

Jus*_*tin 29

以下是我过去的工作方式:运行依赖于配置的服务,可以动态更改实现生命周期界面:IRefreshable:

public interface IRefreshable {
  // Refresh the service having it apply its new values.
  public void refresh(String filter);

  // The service must decide if it wants a cache refresh based on the refresh message filter.
  public boolean requiresRefresh(String filter);
}
Run Code Online (Sandbox Code Playgroud)

控制器(或服务),可以修改配置广播到配置已更改的JMS主题的配置(提供配置对象的名称).然后,消息驱动的bean在实现IRefreshable的所有bean上调用IRefreshable接口契约.

spring的优点在于,您可以自动检测应用程序上下文中需要刷新的任何服务,从而无需显式配置它们:

public class MyCacheSynchService implements InitializingBean, ApplicationContextAware {
 public void afterPropertiesSet() throws Exception {
  Map<String, ?> refreshableServices = m_appCtx.getBeansOfType(IRefreshable.class);
  for (Map.Entry<String, ?> entry : refreshableServices.entrySet() ) {
   Object beanRef = entry.getValue();
   if (beanRef instanceof IRefreshable) {
    m_refreshableServices.add((IRefreshable)beanRef);
   }
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

这种方法在群集应用程序中运行得特别好,其中许多应用程序服务器中的一个可能会更改配置,然后需要注意这些配置.如果要使用JMX作为触发更改的机制,则JMX bean可以在更改任何属性时广播到JMS主题.


shr*_*000 12

我可以想到一个'holder bean'方法(本质上是一个装饰器),持有者bean委托给holdee,它是持有者bean,它作为依赖注入其他bean.没有其他人提到持有人而是持有人.现在,当更改holder bean的配置时,它会使用这个新配置重新创建一个holdee并开始委托给它.


mR_*_*r0g 11

你应该看看JMX.Spring也为此提供支持.