请考虑以下情形。我有一个带有bean的Spring应用程序上下文,该bean的属性应该是可配置的,认为DataSource或MailSender。可变的应用程序配置由单独的Bean管理,我们称之为configuration。
DataSource
MailSender
configuration
管理员现在可以更改配置值,例如电子邮件地址或数据库URL,我想在运行时重新初始化配置的bean。
假设我不能只是简单地修改上述可配置bean的属性(例如,由FactoryBean或构造函数注入创建),而必须重新创建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>
因此,有一个constructorInjectedBean使用构造函数注入的bean 。想像一下,bean的构建非常昂贵,因此,使用原型作用域或工厂代理不是一种选择DataSource。
constructorInjectedBean
我想做的是,每次更新配置时(通过重新创建configurationServicebean constructorInjectedBean并将其重新注入到应用程序上下文和从属bean中)。
configurationServicebean constructorInjectedBean
我们可以放心地假设constructorInjectedBean正在使用接口,因此代理魔术确实是一种选择。
我希望这个问题更加清楚。
我可以想到一种“持有者bean”方法(本质上是一个装饰器),其中持有者bean委托给holdee,而持有者bean作为依赖项注入到其他bean中。除持有人外,没有其他人提及被持有人。现在,当更改Holder bean的配置时,它将使用此新配置重新创建持有人,并开始委派给它。
这是我过去的工作方式:运行依赖于配置的服务,这些配置可以随时更改,以实现生命周期接口: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主题。