如何在其他应用程序上下文中将一个ApplicationContext定义为原型spring bean。此外,我需要将当前上下文作为父项传递给新的应用程序上下文。
详细说明:
我有Bean,代表富客户端应用程序中的一个用户会话。此类管理应用程序上下文的生命周期,以及其他一些对象(如数据库连接)。此会话bean本身由特殊的“启动应用程序上下文”配置。
现在我想要对这个会话bean进行单元测试,但由于在会话bean中创建了会话特定的应用程序上下文,并且有许多依赖于“启动上下文”,因此会出现问题;
示例代码:
public class UserDBAminSession implements ApplicationContextAware, UserSession {
ApplicationContext startupContext;
ApplicationContext sessionContext;
public void setApplicationContext(ApplicationContext startupContext) {...}
public void start() {
createSessionContext() ;
}
private void createSessionContext() {
sessionContext = new ClassPathXmlApplicationContext("admin-session.xml", startupContext);
}
}
出于测试目的,我希望使用以下内容复制createSessionContext函数代码:
sessionContext = startupContext.getBean("adminContext", ApplicationContext.class);
然后我可以创建startupContext的模拟,返回一些存根。或者甚至DI“会话上下文”到春天的bean,在某个未来。但是,我不知道如何将父上下文参数传递给ClassPathXmlApplicationContext构造函数。我尝试这样的东西,但似乎不起作用:
<bean id="adminContext" class="org.springframework.context.support.ClassPathXmlApplicationContext"
scope="prototype" autowire="constructor">
<constructor-arg type="java.lang.String">
<value>admin-session.xml</value>
</constructor-arg>
</bean>
此外,我考虑在顶级创建应用程序上下文并通过setter传递它,但是:
或者制作特殊的“上下文工厂”对象,但它已经不是最好的代码了。
什么看起来很愚蠢,我不能从IoC框架本身的IoC对象。可能是我误读了一些弹簧文档?还有其他想法,如何对这个班级进行单元测试?
答案 0 :(得分:3)
使用FactoryBean
和ApplicationContextAware
接口。
public class ChildApplicationContextFactoryBean implements FactoryBean, ApplicationContextAware {
protected String[] configLocations;
protected ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public Object getObject() throws Exception {
return new ClassPathXmlApplicationContext(configLocations, applicationContext);
}
@Override
public Class getObjectType() {
return ClassPathXmlApplicationContext.class;
}
@Override
public boolean isSingleton() {
return true;
}
public void setConfigLocations(String[] configLocations) {
this.configLocations = configLocations;
}
}
用法:
<bean class="com.skg.ecg.portal.operation.transit.ChildApplicationContextFactoryBean">
<property name="configLocations">
<list>
<value>applicationContext.xml</value>
</list>
</property>
</bean>
答案 1 :(得分:0)
如果我理解正确,您的要求是在手动控制的范围内管理一组bean(在本例中为RIA会话)。
Spring支持scoped beans。您拥有基本的singleton
和prototype
范围,并且网络广告也会获得request
和session
范围。如果您的RIA会话实际上是一个HTTP会话,那么我建议您使用session
-scoped beans而不是手动嵌套的应用程序上下文设计。
如果您的会话与网络无关,那么您仍然可以选择自定义custom scope。在这方面还有更多的工作,但它是容器中定义的扩展点,因此您处于安全的地方。
你最初认为应用程序上下文本身就是父上下文中的bean会起作用,是的,但在这种情况下它可能是不必要的,只会增加复杂性。但是,如果要进一步调查它,请查看SingletonBeanFactoryLocator
,它是用于管理应用程序上下文层次结构的Spring基础结构类。它不会做你想要的具体工作,但它可能会给你一些想法。