mexique1
mexique1

Reputation: 1693

Spring : Injecting the object that launches the ApplicationContext into the ApplicationContext

I want to use Spring inside a legacy application.

The core piece is a class, let's call it LegacyPlugin, that represents a sort of pluggable piece in the application. The problem is that this class is also the database connector, and is used to create lots of other objects, often via constructor injection...

I want to launch an ApplicationContext from the LegacyPlugin, and inject it into the ApplicationContext, via a BeanFactory for example, to create the other objects. The code will then be rewritten, to use setter injection & so on.

I would like to know what is the best way to achieve this. So far, I have a working version using a BeanFactory that uses a ThreadLocal to hold a static reference to the plugin currently executed, but it seems ugly to me...

Below is the code I would like to end up with :

public class MyPlugin extends LegacyPlugin {

    public void execute() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext();
        // Do something here with this, but what ?
        ctx.setConfigLocation("context.xml");
        ctx.refresh();
    }

 }

<!-- This should return the object that launched the context -->
<bean id="plugin" class="my.package.LegacyPluginFactoryBean" />

<bean id="someBean" class="my.package.SomeClass">
    <constructor-arg><ref bean="plugin"/></constructor-arg>
</bean>

<bean id="someOtherBean" class="my.package.SomeOtherClass">
    <constructor-arg><ref bean="plugin"/></constructor-arg>
</bean>

Upvotes: 4

Views: 2436

Answers (2)

mexique1
mexique1

Reputation: 1693

Actually, this doesn't work... It causes the following error :

BeanFactory not initialized or already closed
call 'refresh' before accessing beans via the ApplicationContext

The final solution is to use GenericApplicationContext :

GenericApplicationContext ctx = new GenericApplicationContext();
ctx.getBeanFactory().registerSingleton("plugin", this);
new XmlBeanDefinitionReader(ctx).loadBeanDefinitions(
    new ClassPathResource("context.xml"));
ctx.refresh();

Upvotes: 0

skaffman
skaffman

Reputation: 403461

The SingletonBeanRegistry interface allows you to manually inject a pre-configured singleton into the context via its registerSingleton method, like this:

ApplicationContext ctx = new ClassPathXmlApplicationContext();
ctx.setConfigLocation("context.xml");

SingletonBeanRegistry beanRegistry = ctx.getBeanFactory();
beanRegistry.registerSingleton("plugin", this);

ctx.refresh();

This adds the plugin bean to the context. You don't need to declare it in the context.xml file.

Upvotes: 4

Related Questions