簡體   English   中英

創建ApplicationContext作為Spring bean(通過其他應用程序上下文)

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

我如何在其他應用程序上下文中將一個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傳遞它,但是:

  1. 這只是將問題移到了以上水平,而不是解決。 事實上它已經完成(UserSession - 這是“頂級”)。
  2. 這破壞了RAII模式。
  3. 這需要巨大的代碼重構。

或者制作特殊的“上下文工廠”對象,但它已經不是最好的代碼了。

什么看起來很愚蠢,我不能從IoC框架本身的IoC對象。 可能是我誤讀了一些彈簧文檔?

還有其他想法,如何對這個類進行單元測試?

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

}

用法:

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

如果我理解正確,您的要求是在手動控制的范圍內管理一組bean(在本例中為RIA會話)。

Spring支持scoped bean 您擁有基本的singletonprototype范圍,而webapps也可以獲取requestsession范圍。 如果您的RIA會話實際上是一個HTTP會話,那么我建議您使用session -scoped bean而不是手動嵌套的應用程序上下文設計。

如果您的會話與網絡無關,那么您仍然可以選擇自定義自定義范圍 在這方面還有更多工作,但它是容器中定義的擴展點,因此您處於安全的地方。

你最初認為應用程序上下文本身就是父上下文中的bean會起作用,是的,但在這種情況下它可能是不必要的,只會增加復雜性。 但是,如果要進一步研究它,請查看SingletonBeanFactoryLocator ,它是一個用於管理應用程序上下文層次結構的Spring基礎結構類。 它不會做你想要的具體工作,但它可能會給你一些想法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM