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

2022-08-31 14:37:38

请考虑以下方案。我有一个Spring应用程序上下文,其bean的属性应该是可配置的,think或。可变应用程序配置由单独的Bean管理,我们称之为。DataSourceMailSenderconfiguration

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

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

关于如何实现这一目标的任何想法?我也很乐意收到有关如何组织整个配置的建议。没有什么是固定的。:-)

编辑

为了澄清一些事情:我不是在问如何更新配置或如何注入静态配置值。我试试一个例子:

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

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

我想做的是,每次更新配置时(通过重新创建bean并将其重新注入应用程序上下文和依赖Bean。configurationServiceconstructorInjectedBean

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

我希望能把这个问题说得更清楚一点。


答案 1

以下是我过去的做法:运行依赖于可以动态更改的配置的服务,实现生命周期接口: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 主题广播。


答案 2

我可以想到一种“持有者豆”方法(本质上是一个装饰器),其中持有者豆委托给持有者,并且持有者豆作为依赖关系注入其他豆子。除了持有人之外,没有其他人对被控知识产权人的称呼。现在,当持有者 bean 的配置发生更改时,它会使用此新配置重新创建持有者并开始委派给它。


推荐