开发者

Create ApplicationContext as Spring bean (by other application context)

开发者 https://www.devze.com 2023-01-08 20:39 出处:网络
How i can define one ApplicationContext as prototype spring bean in other application context. Also i need pass current context as parent to new application context.

How i can define one ApplicationContext as prototype spring bean in other application context. 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. 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" .

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

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:

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

Then i can create mock of startupContext, what return some stub. Or even DI "session context" to bean by spring, in some future. But, i don't know how pass parent context parameter to ClassPathXmlApplicationContext constructor. I开发者_如何学Go'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:

  1. This just move problem to above level, not solve. In fact it already done (UserSession - are this "top level").
  2. This broke RAII pattern.
  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. May be i'm misread some spring documentation?

Any other idea, how unit-test this class?


Use FactoryBean and ApplicationContextAware interfaces.

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

Spring has support for scoped beans. You have the basic singleton and prototype scopes, and webapps get the request and session scopes as well. 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.

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. 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. It won't do the specific job you want, but it might give you ideas.

0

精彩评论

暂无评论...
验证码 换一张
取 消