Web应用程序中的Spring应用程序上下文刷新

时间:2015-08-20 19:53:44

标签: java spring spring-mvc

在我的应用程序中,在服务器启动期间,spring bean DAO类使用spring jdbc模板从数据库中读取值并存储在哈希映射中。

我需要在运行时重新加载一组特定的bean而不重新启动应用服务器。

以下是我的代码段。如果需要我可以发布更多

private void setMessageDetails() {
messageContentDetails= namedParameterJdbcTemplate.queryForObject(messageContentSql,nameParamMap, new MessageContentRowMapper());
}

MessageContentRowMapper.java maps the resultset values to valuesMap below

public class MessageContentDetails {
private Map<String, Map<String, String>> valuesMap= new HashMap<String, Map<String, String>>();
 ..setters/getters..
} 

现在,如果任何数据库值发生变化,我需要重新初始化MessageContentDetails.java并使用新值更新hashmap,并再次自动装配此类的引用,无论它在应用程序启动期间以前是否已自动装配/注入。

我的问题是

  1. 我可以使用applicationContext.refresh()方法刷新一个或一组几个spring bean。
  2. 有没有更好的方法来重新加载具有一些静态值的spring bean,这些值需要在运行时重新加载?
  3. 使用此方法可能会对线程产生什么影响。我的应用程序分布在3个不同的数据中心,有多个jvms。
  4. 任何与上述问题相关的链接都会非常有用。

    我使用的是JAVA 1.6 WebSphere Spring 3.1.0版本,而MessageContentDetails bean是一个在spring xml中配置而没有注释的spring bean。

1 个答案:

答案 0 :(得分:2)

我不确定这是否可以通过Spring开箱即可实现,可能有一些技巧和多个上下文。默认情况下,Spring会在refresh的某些上下文中销毁所有单身人士。

但是,考虑到您的情况,如果没有Spring的参与,实现这一要求并不困难。

您需要做的是在运行时更新静态Map,即:)

一般解决方案:

1)介绍Web服务,它允许您为更新提供新值,

2)创建依赖于可更新bean Observers并提供块释放机制的bean,

3)

  • 通过反射或多态来编写通用映射,它允许您更新任何bean的静态值

  • 在Web服务负载和目标bean状态之间编写特定映射。

让我们从1开始:

@Controller
public class BeanUpdateController {

@Autowired
private UpdateService updateService;


@RequestMapping(value = "/updateState", method = RequestMethod.POST)
@ResponseBody
public UpdateResponse handleUpdateRequest(@Valid @RequestBody someXMLYouDefine updateRequest) {

    return updateService.execute(voucher);
}

请注意,您还可以使用RequestMethod.GET和网址参数。

但是,您的想法是以一些可解析的格式传输要更新的Bean的名称,字段名称和适当的值。

让我们来3:

@Component
public class BeanLocator implements ApplicationContextAware {

private static ApplicationContext context;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    context = applicationContext;   
}

public Object getBean(String beanName)  {

    return context.getBean(beanName);

}

protected ApplicationContext getContext() {

    return context;
}

此服务允许您按名称查找Bean,该名称包含在Web服务的有效负载中。

获得bean后,您有几个选择:

1)让'updateable'Beans实现一些接口,例如Updatable,并传递它们将自行更新的字段名称和值。

2)使用反射,也许是这样的:

表示有效负载中的每个字段名称:

Field field = acquiredBean.getClass().getDeclaredField("fieldNameFromThePayload");

如果它是原始的,你可以这样做:

field.setAccessible(true);
field.set(acquiredBean,"valueFromPayload")

如果它是Collection或Map,并且如果使用表示此结构的XSD,则可以直接将生成的类中的列表映射到目标bean。当然,你也可以手动迭代。

实现选项3的最简单但最不灵活的方法是在GET请求上简单地将值作为URL参数传递,然后让服务获得对Bean的映射的引用,然后更新。

现在回到第二步,如果它不是关键业务,你可以跳过它。

每个可能依赖于'可更新'bean的bean都应该实现Observer接口。当更新请求到来时,它们会通过策略模式切换实现,以便在进程中有更新时对所有传入请求进行排队。 bean更新后,应发送确认。这将触发另一个侦听服务通知,该通知将取消阻止排队请求并继续处理。

应将更新的Web服务请求广播到具有可更新bean的所有节点。