spring bean配置
最近,我遇到了一个我从未遇到过的问题:引入了基于运行时引入的配置来重新连接Bean内部的功能。 这对于简单的配置更改或交换掉诸如Strategy或Factory类之类的东西很有用,而不是重建应用程序上下文的复杂部分。
我能够找到一些有关如何执行此操作的注释,但我认为有些人可能会发现我的注释和代码示例很有用,特别是因为我可以确认该技术在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重新配置应用程序而无需停机的基础知识。
相关文章 :
- 零XML的Spring配置
- Spring依赖注入技术的发展
- Spring MVC3 Hibernate CRUD示例应用程序
- 使用Spring AOP进行面向方面的编程
- Spring MVC开发–快速教程
翻译自: https://www.javacodegeeks.com/2011/09/swapping-out-spring-bean-configuration.html
spring bean配置