简体   繁体   English

创建ApplicationContext作为Spring bean(通过其他应用程序上下文)

[英]Create ApplicationContext as Spring bean (by other application context)

How i can define one ApplicationContext as prototype spring bean in other application context. 我如何在其他应用程序上下文中将一个ApplicationContext定义为原型spring bean。 Also i need pass current context as parent to new application context. 此外,我需要将当前上下文作为父应用程序上下文传递。

Details: 细节:

I have Bean, that represent one user sessions in rich client application. 我有Bean,代表富客户端应用程序中的一个用户会话。 This class manage lifetime of application context, and few other objects (like database connection). 此类管理应用程序上下文的生命周期,以及其他一些对象(如数据库连接)。 This session beans itself configured by special "start-up application context" . 此会话bean本身由特殊的“启动应用程序上下文”配置。

Now i'm want unit test this session beans, but have trouble because session specific application context created inside session bean, and has many depend to "start-up context"; 现在我想要对这个会话bean进行单元测试,但由于在会话bean中创建了会话特定的应用程序上下文,并且有许多依赖于“启动上下文”,所以有麻烦;

Example code: 示例代码:

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);
    }
}

For testing purpose i want relapse createSessionContext function code with something like this: 出于测试目的,我想复制createSessionContext函数代码,如下所示:

sessionContext = startupContext.getBean("adminContext", ApplicationContext.class);

Then i can create mock of startupContext, what return some stub. 然后我可以创建startupContext的模拟,返回一些存根。 Or even DI "session context" to bean by spring, in some future. 或者甚至DI“会话上下文”到春天的bean,在某个未来。 But, i don't know how pass parent context parameter to ClassPathXmlApplicationContext constructor. 但是,我不知道如何将父上下文参数传递给ClassPathXmlApplicationContext构造函数。 I'm try something like this, but it seems not work: 我尝试这样的东西,但似乎不起作用:

<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>

Also I'm think about create application context on top level and pass it by setter, but: 此外,我考虑在顶层创建应用程序上下文并通过setter传递它,但是:

  1. This just move problem to above level, not solve. 这只是将问题移到了以上水平,而不是解决。 In fact it already done (UserSession - are this "top level"). 事实上它已经完成(UserSession - 这是“顶级”)。
  2. This broke RAII pattern. 这破坏了RAII模式。
  3. This need huge code refactoring. 这需要巨大的代码重构。

Or make special "context factory" objects, but it harder already not best code. 或者制作特殊的“上下文工厂”对象,但它已经不是最好的代码了。

What look stupid, I can't IoC objects from IoC framework itself. 什么看起来很愚蠢,我不能从IoC框架本身的IoC对象。 May be i'm misread some spring documentation? 可能是我误读了一些弹簧文档?

Any other idea, how unit-test this class? 还有其他想法,如何对这个类进行单元测试?

Use FactoryBean and ApplicationContextAware interfaces. 使用FactoryBeanApplicationContextAware接口。

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;
    }

}

Usage: 用法:

<bean class="com.skg.ecg.portal.operation.transit.ChildApplicationContextFactoryBean">
    <property name="configLocations">
        <list>
            <value>applicationContext.xml</value>
        </list>
    </property>
</bean>

If I understand you correctly, your requirement is for managing a collection of beans within a manually-controlled scope (your RIA session, in this case). 如果我理解正确,您的要求是在手动控制的范围内管理一组bean(在本例中为RIA会话)。

Spring has support for scoped beans . Spring支持scoped bean You have the basic singleton and prototype scopes, and webapps get the request and session scopes as well. 您拥有基本的singletonprototype范围,而webapps也可以获取requestsession范围。 If your RIA session is actually an HTTP session, then I suggest you use session -scoped beans instead of your manually-nested application context design. 如果您的RIA会话实际上是一个HTTP会话,那么我建议您使用session -scoped bean而不是手动嵌套的应用程序上下文设计。

If your sessions are not web-related, then you still have the option of definign your own custom scope . 如果您的会话与网络无关,那么您仍然可以选择自定义自定义范围 There's more work in this, but it is a defined extension point in the container, so you're on safe ground. 在这方面还有更多工作,但它是容器中定义的扩展点,因此您处于安全的地方。

Your original idea of application contexts being themselves beans within a parent context would work, yes, but it's probably unnecessary in this case, and just adds complexity. 你最初认为应用程序上下文本身就是父上下文中的bean会起作用,是的,但在这种情况下它可能是不必要的,只会增加复杂性。 If you want to investigate it further, however, have a look at the SingletonBeanFactoryLocator , which is a Spring infrastructure class for managing hierarchies of application contexts. 但是,如果要进一步研究它,请查看SingletonBeanFactoryLocator ,它是一个用于管理应用程序上下文层次结构的Spring基础结构类。 It won't do the specific job you want, but it might give you ideas. 它不会做你想要的具体工作,但它可能会给你一些想法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM