Home | FAQ | Contact me

A Discussion on Injection

The beginning of this discussion is purely a condensation of http://martinfowler.com/articles/injection.html.

"Now if I'm using this class for just myself, this is all fine and dandy. But what happens when my friends are overwhelmed by a desire for this wonderful functionality and would like a copy of my program? If they also store their movie listings in a colon delimited text file called movies1.txt then everything is wonderful. If they have a different name for their movies file, then it's easy to put the name of the file in a properties file. But what if they have a completely different form of storing their movie listing: a SQL database, an XML file, a web service, or just another format of text file? In this case we need a different class to grab that data. Now because I've defined a MovieFinder interface, this won't alter my moviesDirectedBy() method. But I still need to have some way to get an instance of the right finder implementation into place."

                                +---------------+
 +---------------+              |  <interface>  |
 |  MovieLister  | -----------> |  MovieFinder  |
 +---------------+              +---------------+
        |                               ^
        |                               |
        |                               |
        |    (creates)       +-------------------+
        +------------------> |  MovieFinderImpl  |
                             +-------------------+

"The implementation class for the finder (MovieFinderImpl) isn't linked in at compile time since there's no way to know how friends are are going to use. Instead, a "plug-in" must be created. But how to make the link so that the lister class (MovieLister) can remain ignorant of the implementation class yet still talk to an instance to the work? Inversion of control (IoC)."

Code to consider in this discussion...

public interface MovieFinder
{
    /**
     * The point of this example is that this method must be independent of how movies are
     * actually stored.
     */
    public List< String > findAll();
}

public class MovieLister
{
    private MovieFinder finder;

    public MovieLister()
    {
        finder = new ColonDelimitedMovieFinder( "movies.txt" );
    }

    /**
     * Finder object to return an array of movies by a specific director.
     */
    public Movie[] moviesDirectedBy( String director )
    {
        List allMovies = finder.findAll();

        for( Iterator it = allMovies.iterator(); it.hasNext(); )
        {
            // return every film known...
            Movie movie = ( Movie ) it.next();

            // if the film was not directed by the specified director, remove it from the list
            if( !movie.getDirector().equals( directory ) )
                it.remove();
        }

        // make an array of these movies directed by the specified director
        return ( Movie[] ) allMovies.toArray( new Movie[ allMovies.size() ] );
    }
}

Inversion of Control

In a user interface, the control of the program is "inverted" in that it's moved away from the caller to the framework. In our example, we obviously cannot instantiate the finder implementation directly because that would have to occur during compilation. A consumer would have to follow a convention that allows a separate assembler module to "inject" the implementation into the lister.

So, "inversion of control" is too generic a term and confusing in this discussion. A better one, one that many are using today, is "dependency injection."

Dependency Injection

There are three main types of dependency injection, interface injection, setter injection and constructor injection. (In the literature, you often see these respectively as type 1 injection, type 2 injection and type 3 injection.)

Constructor (Type 3) Injection

This type uses a constructor to decide how to inject a finder implementation into the lister class. The requirement is for the lister class to define a constructor that includes everything it needs injected in order to get the work done.

    public class MovieLister
    {
        public MovieLister( MovieFinder finder )
        {
            this.finder = finder;
        }
    }

And, the finder itself must have the filename containing the list injected.

    class ColonMovieFinder
    {
        private String    filename;

        public ColonMovieFinder( String filename )
        {
            this.filename = filename;
        }
    }

The container must be told which implementation class to associate with each interface, and which string to inject into the finder.

    class MutablePicoContainer
    {
        private MutablePicoContainer configureContainer()
        {
            MutablePicoContainer pico         = new DefaultPicoContainer();
            Parameter[]          finderParams =
            {
                new ConstantParameter( "movies1.txt" )
            };

            pico.registerComponentImplementation( MovieFinder.class, ColonMovieFinder.class, finderParams );
            pico.registerComponentImplementation( MovieLister.class );
            return pico;
        }
    }

The configuration code is typically set up in a separate class. For this example, each friend who uses the lister might write the appropriate configuration code in some set-up class of his own. It's common to hold this sort of configuration information in separate files. you can write a class to read a config file and set up the container appropriately. Such a container would parse, e.g.:, XML and then configure an underlying container. The goal here is to separate the configuration file format from the underlying mechanism.

    public TestMutablePicoContainer
    {
        public void testWithPico()
        {
             MutablePicoContainer pico   = configureContainer();
             MovieLister          lister = ( MovieLister ) pico.getComponentInstance( MovieLister.class );
             Movie[]              movies = lister.moviesDirectedBy( "Sergio Leone" );

             assertEquals( "Once Upon a Time in the West", movies[0].getTitle() );
        }
    }

This is constructor injection.

Setter (Type 2) Injection

Spring supports both constructor and setter injection, but Spring developers tend to favor setter injection.

To get the movie lister to accept injection, define a setting method for that service:

    public class MovieLister
    {
        private MovieFinder finder;

        public void setFinder( MovieFinder finder ) { this.finder = finder; }
    }

Define a setter for the filename.

    public class ColonMovieFinder
    {
        public void setFilename( String filename ) { this.filename = filename; }
    }

The third step is to set up the configuration for the files. Spring supports configuration through XML files and also through annotation, but we'll use XML here.

    <beans>
        <bean id="MovieLister" class="spring.MovieLister">
            <property name="finder">
                <ref local="MovieFinder" />
            </property>
        </bean>
        <bean id="MovieFinder" class="spring.ColonMovieFinder">
            <property name="filename">
                <value>movies1.txt</value>
            </property>
        </bean>
    </beans>

The test then looks like this.

    public TestMutablePicoContainer
    {
        public void testWithSpring() throws Exception
        {
            ApplicationContext ctx    = new FileSystemXmlApplicationContext( "spring.xml" );
            MovieLister        lister = ( MovieLister ) ctx.getBean( "MovieLister" );
            Movie[]            movies = lister.moviesDirectedBy( "Sergio Leone" );

            assertEquals( "Once Upon a Time in the West", movies[ 0 ].getTitle() );
        }
    }

Interface (Type 1) Injection

Interface injection is more invasive and complex because you have to write a lot of interfaces to get things sorted out. It's a lot of work assembling multiple components and dependencies which is exactly why lightweight containers such as Spring go with setter or constructor injection.

Setter vs. Constructor Injection

This choice mirrors a more general issue of object-oriented programming. Some assert that it's best to create valid objects at construction time. Constructors with parameters give a clear statement of what it means to create a valid object at an obvious place. When there's more than one way to do it, create multiple constructors that translate the different possibilities. You also hide any fields that are supposed to be immutable simply by not providing a setter: if something is not supposed to change, then not offering a setter communicates that. However, lots of arguments to a constructor can be very messy. If there are multiple ways to construct a valid object, it's not apparent through constructors. Factory methods make use of a combination of private constructors and setters to implement their work. The problem with classic Factory methods for component assembly is that they are usually seen as static, which you can't have in interfaces. Constructors also suffer when you have simple arguments such as strings. Setter-based injection means each setter method's name indicates exactly what's going on. (Constructors require you to count argument positions.) One approach is to begin with constructor injection, but be ready to switch over to setter injection when the going gets hairy.

Advantages to Constructor Injection

Therefore, the advantages are completeness of the object and self-documentation as to what actually constructs it. Moreover, constructor injection allows you to make the instance variables "final" meaning more immutable which is a clear advantage for multithreading.

Code or Configuration Files

A related issue is whether to use configuration files or just code in an API to wire up a service. A separate XML or properties files seems like a good way to handle the soft details. However, code is going to be clearer and can handle conditional steps when set-up gets complex: write separate builder classes that do the assembly and use a configuration file to select between them. A good idea is to do all configuration programmatically and treat a separate configuration file as an optional feature to override otherwise infrequently overridden details of the implementation.

My Own Experience

Setter injection is simpler and begins with constructing a basic object with reasonable defaults which are then overridden through the use of setters. I find that setter injection is dramatically chaotic when one does not or cannot know which pieces of information must be filled out in order to configure a correct object. And that's just the beginning: what order must the pieces be assembled could be a problem for one can easily imagine order-dependency in the composition of more complex objects. There might even be totally circular dependencies. Last, it's easy to over-look a setter or two. In constructor injection, the author establishes a (presumably) correct object via explicit arguments (and in the correct order). The constructor doesn't succeed unless and until a correctly configured object is created. Once the construct returns, you know you're done creating the object.

Solutions

Spring promotes a choice between the two types of injection, but for flexibility uses mostly setter injection. It solves the problem of required vs. optional setters by offering the @Required annotation. Any required setters that have not been called on an object leave the object in a partially initialized state. This is expressly pointed out if you enforce the checking by registering a RequiredAnnotationBeanPostProcessor. There are two ways to do this; see http://www.mkyong.com/spring/spring-dependency-checking-with-required-annotation/. At runtime, the following will issue:
    org.springframework.beans.factory.BeanInitializationException:
        Property 'person' is required for bean 'CustomerBean'