tags:

views:

2118

answers:

3

I'm dealing with a legacy code base where a class which is not wired up in spring needs to obtain a class that is wired up in spring. I was hoping to create a factory class that was wired up on startup and then I could just call the getInstance() method to obtain a wired up object. What is the best way to go about this?

Example:

public class LegacyA {
    public void doSomething() {
        ...
        Foo foo = FooFactory.getInstance();
        ...
    }
}

public class FooFactory {
    private static Foo foo;

    public static Foo getInstance() {
        if (foo == null) throw new IllegalStateException();
        return foo;
    }
}

I need FooFactory to be wired up on startup so that LegacyA can simply call getInstance() so that it returns an instance of Foo (which is also a bean defined in the application context).

<bean id="legacyA" class="LegacyA"/>

<bean id="foo" class="Foo"/>

<!-- I need this bean to be injected with foo so that the FooFactory can return a foo -->
<bean id="fooFactory" class="FooFactory"/>

Edit: I had to re-work my example a bit as I got it a bit confuzzled in my own head...

+1  A: 

Is defining the bean as a singleton in the Spring configuration of use here ? You can then inject it into LegacyB using property or constructor inject (my preference is the latter) and then only the one instance is available.

EDIT: Re. your changed question (!) I not sure why you don't simply inject Foo again as a singleton into your factory. Note also that you can use the getInstance() method via the Spring configs by using factory-method, and maintain injection through all classes.

Brian Agnew
Sorry for having to change the question slightly on you. I didn't realise until a little later than I had the whole question wrong in my head.
digiarnie
Thanks for the heads up. That's not a problem. Answer modified appropriately.
Brian Agnew
+2  A: 

Using statics like this really goes against the grain of Spring IoC, but if you really have to use them, then I would suggest writing a simple Spring hook which takes the Foo and injects it into the FooFactory, e.g.

public class FooFactoryProcessor implements InitializingBean {

    private Foo foo;

    public void setFoo(Foo foo) {
     this.foo = foo;
    }

    public void afterPropertiesSet() throws Exception {
     Foofactory.setFoo(foo);
    }
}

And in your XML:

<bean id="foo" class="Foo"/>

<bean class="FooFactoryProcessor">
   <property name="foo" ref="foo"/>
</bean>

No need to modify Foo or FooFactory

skaffman
agreed in regards to your static comment. I would normally never go down that route however the legacy code uses this static class all over the place and the best way to hook in this new spring object without breaking the existing code is to keep the calls to the old static class and have that static class use the new and improved spring wired object.
digiarnie
Why don't you just let spring manage FooFactory directly. You don't really need the abstraction the is "FooFactoryProcessor". You can add a non static property setter to FooFactory to set foo on it.
Michael Wiles
This is true, yes, but I was going along the lines of the smallest number of changes to legacy code, which is what the OP seemed to be after.
skaffman
A: 

In addition to skaffman's answer you must be very very careful about initialization order.

When using Spring beans only the framework will automatically figure out the correct order of initializing stuff. As soon as you are doing singleton tricks however, this may break if you are not careful.

In other words make sure that LegacyA cannot be run before application context finishes loading.

Gregory Mostizky