A Comparison of Some Dependency Injection Frameworks: Part 7 Spring JavaConfig

Introduction

This series of articles is examining a number of dependency injection frameworks.  Part 3 of the series looked at the Spring framework configured with XML.  Part 5 and part 6 looked at Guice.  This article will apply the same tests to the Spring framework but configured in code using the JavaConfig download.

Code

The code for this article is available.

Note that JavaConfig used to be a separate download but is now being folded into core Spring (in Spring 3.0 and later versions).  However for this article I used the separate download version and Spring 2.2. 

JavaConfig

Spring JavaConfig is very similar to Spring XML except that all configuration is done in code rather than using XML.  The syntax for retrieving objects from a configured container is identical to Spring XML.

Specifically configuration is done by writing a class and annotating it with the @Configuration annotation.   We then configure individual objects by writing methods within the class.  We make the methods return the object we require, usually by just instantiating it with the ‘new’ keyword.  Then we annotate the method with the @Bean annotation:

@Configuration
public class ApplicationConfig {
      @Bean
      public Movie AndreiRublevMovie() {
            return new Movie("Andrei Rublev", "Andrei Tarkovsky");
      }

The effect of this is identical to configuring a bean in XML in Spring XML.  The method name in JavaConfig (AndreiRublevMovie) corresponds to the ID of the object in Spring XML.  As we shall see, the various techniques for configuring beans in Spring XML are also available in JavaConfig.

We configure our container with a different application context and a constructor that takes the name of the configuration class (or classes):

            JavaConfigApplicationContext context = new JavaConfigApplicationContext(ApplicationConfig.class);

We can now retrieve objects from the container using the getBean method and the method name as a (string) identifier as usual:

            Movie andreiRublev = (Movie) context.getBean("AndreiRublevMovie");

Testing Spring JavaConfig

JavaConfig uses exactly the same syntax for retrieving and using objects as does Spring XML.  As a result our StartUp class for JavaConfig is almost identical to the StartUp class for Spring XML.  The only difference is the application context creation described above.

So the only code differences between the tests for Spring XML and JavaConfig are in the way the container is configured.  As you can see this is very straightforward.

I’m not going to go through the configuration for all the tests as a result. 

Note that:

  • For tests 2 and 3 it’s very easy to define different objects to be injected into the same class in different circumstances: you just instantiate two instances of the class in different methods and give them the dependent objects as shown below, where simpleMovieFinder and colonDelimitedMovieFinder are configuration methods that return the appropriate MovieFinder objects.
  • For tests 4 and 5, to specify singleton or prototype scope you just add the ‘scope’ annotation (the default is singleton).  This is also shown below.
      @Bean(scope=DefaultScopes.SINGLETON)
      public MovieLister simpleMovieLister() {
            return new MovieLister(simpleMovieFinder());
      }
      
      @Bean(scope=DefaultScopes.PROTOTYPE)
      public MovieLister colonDelimitedMovieLister() {
            return new MovieLister(colonDelimitedMovieFinder());
      }
  • For test 6, to use a factory method to create a class is again intuitive and simple.  You just create the factory in one configuration method and then call the factory method on it directly where you want your object returned in a second configuration method:
      @Bean(scope=DefaultScopes.PROTOTYPE)
      public ComplexMovieListerFactory complexMovieListerFactory() {
            return new ComplexMovieListerFactory();
      }
      
      @Bean(scope=DefaultScopes.PROTOTYPE)
      public MovieLister complexMovieLister() {
            return complexMovieListerFactory().build();
      }

Comments

JavaConfig does seem a step forward compared to the XML configuration problems we have previously been wrestling with for dependency injection.  In  particular it has the following advantages:

  • There is no XML, and the configuration in code means that there is some level of compile-type checking.  However, you can (and usually do) use string identifiers to retrieve objects, so there is still scope for typos that won’t manifest themselves until runtime.   Note that it is possible to retrieve objects from the container by type to avoid this.
  • There is no need for code changes in classes (no annotations are applied to the classes you are injecting or injecting into)
  • The configuration class is very simple, and uses syntax familiar to any developer.  Unlike any other framework here you’re not being compelled to learn something radically different to use JavaConfig.  All you have to learn is how the few attributes you need are used.
  • We’re configuring in code using usual Java syntax.   This makes some of the constructs we have special syntax for in other frameworks seem very odd and cumbersome.  In particular the factory test above almost seems silly: we get our object by returning it from a method, obviously we can do that by just instantiating it OR by instantiating another class that will build it and return it from a build method.

JavaConfig is so simple that it makes you wonder why you need a framework at all.  Previously in this series of articles I’ve suggested that the tests may be a little more advanced than you’d actually use in practice.  But apart from tests 3 and 4 (singleton and prototype creation) none of the tests really need the Spring framework at all now we’re using JavaConfig.  We could take all the attributes out and just use the ApplicationConfig class as a factory class.  Even tests 3 and 4 could easily be coded without the framework.  More on this later.

Conclusion

Code configuration as used in JavaConfig seems a simple and intuitive alternative to the more usual XML configuration.

Part 8 of this series will look at Microsoft’s Unity framework.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s