一尘不染

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

spring

请考虑以下情形。我有一个带有bean的Spring应用程序上下文,该bean的属性应该是可配置的,认为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>

因此,有一个constructorInjectedBean使用构造函数注入的bean 。想像一下,bean的构建非常昂贵,因此,使用原型作用域或工厂代理不是一种选择DataSource

我想做的是,每次更新配置时(通过重新创建configurationServicebean constructorInjectedBean并将其重新注入到应用程序上下文和从属bean中)。

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

我希望这个问题更加清楚。


阅读 1151

收藏
2020-04-15

共2个答案

一尘不染

我可以想到一种“持有者bean”方法(本质上是一个装饰器),其中持有者bean委托给holdee,而持有者bean作为依赖项注入到其他bean中。除持有人外,没有其他人提及被持有人。现在,当更改Holder bean的配置时,它将使用此新配置重新创建持有人,并开始委派给它。

2020-04-15
一尘不染

这是我过去的工作方式:运行依赖于配置的服务,这些配置可以随时更改,以实现生命周期接口: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);
}

可以修改一条配置的控制器(或服务),广播到配置已更改的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);
   }
  }
 }
}

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

2020-04-15