Remove all dependency lookups in Spring application

Dependency lookup is a call to any method on a Spring Container’s bean factory in your app. It is used for retrieving a bean from another bean. It may be of use in a circumstance where a bean needs to collaborate with another bean having different scope (or lifecycle). specifically, between a singleton and a prototype bean.

To make use of dependency lookup, just simply make your bean (typically the singleton bean) implement the ApplicationContextAware, which will let your bean access the ApplicationContext. After that, you can make a call to the getBean() method of the ApplicationContext to retrieve the bean you need, as shown below:

Listing 1. Using Dependency Lookup in business code

protected Foo createBean() {
    return this.applicationContext.getBean("foo", Foo.class);
}

This approach is, however,  not recommended. Because your business code is coupled to the Spring Framework, and it breaks the Inversion of Control principle.

As far as I know, there are two solutions to this.

1. Lookup Injection: First, you can make use of the so-called lookup injection feature of Spring Framework. To get things done, simply make the method createBean() above abstract, as shown below:

Listing 2. Modified createBean() method

protected abstract Foo createBean();

But where is the implementation? Well, Spring will take care of that. All you have to do is registering this method as a lookup method in your configuration metadata, and Spring will automatically implement it at runtime.

Listing 3. Register the lookup method


<bean id="foo" class="x.y.Foo" scope="prototype">
</bean>
<bean id="bar" class="x.y.Bar">
<lookup-method name="createBean" bean="foo"/>
</bean>

2. Employ the ServiceLocatorFactory: The second approach is to use the ServiceLocatorFactoryBean class. To make use of it, create a new interface FooCreator:

Listing 4. The FooCreator interface

public interface FooCreator {
    Foo createFoo(String fooId);
}

As you can see, this approach this similar to the previous.  Again, where’s the implementation? And yet again, all you have to do is registering a few things at your configuration metadata, as shown below:

Listing 5. Register your bean factory

<bean id="myFooCreator" class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
    <property name="serviceLocatorInterface" value="x.y.FooCreator">
</bean>

To retrieve the foo bean (the one with a prototype scope) in another bean, just make a call:

Foo f = myFooCreator.createFoo("foo");

Bear in mind that the myFooCreator bean above is just a dynamic proxy created by Spring at runtime, and Spring requires the CGLIB library to handle that, so make sure you have the CGLIB in your classpath.

Conclusion

You should not use dependency lookup in your business code, as it forgo the Dependency Injection, which is the core principle of Spring Framework, and it couple your business code to the Spring Framework. Instead, you should use the Lookup Injection feature of Spring, or make use of the ServiceLocatorFactoryBean, which allows you to create a custom locator.

P/S: You should consult this article: http://java-x.blogspot.com/2007/01/spring-prototype-beans-with-singletons.html, as I see it very useful.

About javarchive

I'm swimming into the depth of Java world
This entry was posted in Tips and tagged , , , . Bookmark the permalink.

2 Responses to Remove all dependency lookups in Spring application

  1. Sarvesh says:

    Hi I am new to Spring and have a question which I would like to get some advice on. I have a scenario:
    abstract class A{
    }

    abstract class B extends A{
    }

    class C extends B{}

    class D extends B{}

    I have a factory
    B getInstance(String name){
    if(name.equals(“A”)
    return new A();
    else return new B();
    }

    How can I implement the same in Spring?

    Thank

  2. javarchive says:

    First, the class A is abstract, so it cannot be instantiated unless you use the lookup-method directive and the abstract method is a factory method, as described in my post.

    Second, to create new class instance using its class name:
    – You must declare each instance of both class A and B, in your configuration metadata (such as …). Remember that these beans must be Prototype beans.
    – Create factory methods for both class A and B, using lookup injection or the ServiceLocatorFactory (such as: A createA(String aId)) in a factory class/interface.
    – In your factory method, instead of using the new operator, you should call the factory methods you created above.

    And whatever method you use, just make sure not to use/import Spring classes.

Leave a comment