spring bean配置_在运行时交换出Spring Bean配置

spring bean配置

如今,大多数Java开发人员都定期与Spring打交道,而我们当中的许多人都已经熟悉了它的功能和局限性。

最近,我遇到了一个我从未遇到过的问题:引入了基于运行时引入的配置来重新连接Bean内部的功能。 这对于简单的配置更改或交换掉诸如StrategyFactory类之类的东西很有用,而不是重建应用程序上下文的复杂部分。

我能够找到一些有关如何执行此操作的注释,但我认为有些人可能会发现我的注释和代码示例很有用,特别是因为我可以确认该技术在Spring 1.2.6之前的版本中有效。 不幸的是,并不是我们所有人都有幸成为每个图书馆中最新最好的图书馆。

问题范围

我将概述的方法主要是针对单个bean的更改,尽管可以轻松扩展此代码以更改多个bean。 可以通过JMX或向管理员公开的其他UI调用它。

它没有涵盖的一件事是在整个应用程序中重新布线单例–可以想象,这可以通过对当前应用程序上下文的某种反思和检查来完成,但是在大多数应用程序中,除非它们具有某种临时关闭或关闭的方式,否则可能不安全。在整个应用程序中进行更改的同时,将所有处理阻塞一段时间。

代码

这是示例代码。 它将获取一个包含bean定义的字符串列表,并将它们连接到新的临时Spring上下文中。 您将看到可以提供父上下文,这在您的新bean定义需要引用应用程序中已经配置的bean时很有用。

public static <T> Map<String, T> extractBeans(Class<T> beanType,
   List<String> contextXmls, ApplicationContext parentContext) throws Exception {

   List<String> paths = new ArrayList<String>();
   try {
      for (String xml : contextXmls) {
         File file = File.createTempFile("spring", "xml");
         // ... write the file using a utility method
         FileUtils.writeStringToFile(file, xml, "UTF-8");
         paths.add(file.getAbsolutePath());
      }

      String[] pathArray = paths.toArray(new String[0]);
      return buildContextAndGetBeans(beanType, pathArray, parentContext);

   } finally {
      // ... clean up temp files immediately if desired
   }
}

private static <T> Map<String, T> buildContextAndGetBeans(Class<T> beanType,
               String[] paths, ApplicationContext parentContext) throws Exception {

   FileSystemXmlApplicationContext context =
      new FileSystemXmlApplicationContext(paths, false, parentContext) {
         @Override  // suppress refresh events bubbling to parent context
         public void publishEvent(ApplicationEvent event) { }
      };

   try {
      // avoid classloader errors in some environments
      context.setClassLoader(beanType.getClassLoader());
      context.refresh(); // parse and load context
      Map<String, T> beanMap = context.getBeansOfType(beanType);

      return beanMap;
   } finally {
      try {
         context.close();
      } catch (Exception e) {
         // ... log this
      }
   }
}

如果查看buildContextAndGetBeans() ,您将看到它通过使用提供的XML bean定义文件构建Spring上下文来完成大部分工作。 然后,它返回所请求类型的构造bean的映射。

注意:由于临时Spring上下文已被破坏,因此请确保您的bean没有生命周期方法,该方法会导致它们在停止或破坏时处于无效状态。

这是一个Spring上下文的示例,可用于重新连接组件。 想象一下,我们有一个电子商务系统,可以进行欺诈检查,但是可以使用多种策略来检查欺诈。 我们可能希望从我们的服务类中交换这些内​​容,而不必停止并重新配置应用程序,因为这样做会造成业务损失。 也许我们正在发现对该系统的特定滥用,可以通过更改用于定位欺诈性订单的策略来更好地解决。

这是一个示例XML定义,可用于重新连接我们的FraudService

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
   <bean id="fraudStrategy" class="com.example.SomeFraudStategory">
      <!-- example of a bean defined in the parent application context that we can reference -->
      <property name="fraudRuleFactory" ref="fraudRuleFactory"/>
   </bean>
</beans>

这是可以用来通过引用已定义的欺诈策略重新连接Bean的代码,假设您将其包含在名为SpringUtils的实用工具类中:

public class FraudService implements ApplicationContextAware {

   private ApplicationContext context;
   // volatile for thread safety (in Java 1.5 and up only)
   private volatile FraudStrategy fraudStrategy;

   @Override // get a handle on the the parent context
   public void setApplicationContext(ApplicationContext context) {
      this.context = context;
   }

   public void swapFraudStategy(String xmlDefinition) throws Exception {
      List<Sting> definitions = Arrays.asList(xmlDefinition);
      Map<String, FraudStrategy> beans =
         SpringUtils.extractBeans(FraudStrategy.class, definitions, context);
      if (beans.size() != 1) {
         throw new RuntimeException("Invalid number of beans: " + beans .size());
      }
      this.fraudStrategy = beans.values().iterator().next();
   }

}

在那里,您拥有了! 可以适当地扩展此示例以满足您的需求,但是我认为它展示了如何动态创建Spring上下文并使用其bean重新配置应用程序而无需停机的基础知识。

参考: 在运行时从我们的JCG合作伙伴Carfey Software博客上 交换Spring Bean配置

相关文章 :

翻译自: https://www.javacodegeeks.com/2011/09/swapping-out-spring-bean-configuration.html

spring bean配置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值