Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Wire a Static Class

Tags:

java

spring

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

like image 855
digiarnie Avatar asked Jul 28 '09 08:07

digiarnie


3 Answers

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

like image 103
skaffman Avatar answered Oct 29 '22 00:10

skaffman


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.

like image 32
Brian Agnew Avatar answered Oct 29 '22 00:10

Brian Agnew


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.

like image 38
Gregory Mostizky Avatar answered Oct 29 '22 00:10

Gregory Mostizky