Monday, 11 April 2011

More Spring Java based DI

Yesterday’s blog covered the new Java based dependency injection (DI) feature of Spring 3 demonstrating how to create and instantiate a simple factory class using @Configuration annotation. So far so good, but those clever chaps at Springsource have thought this through quite thoroughly and provided much more flexibility than I demonstrated yesterday.

This blog goes into slightly more depth than yesterday’s demonstrating how to use some of those additional features.

The first point to make is that if you’ve ever worked on a professional Spring app, then you’ll know that Spring config XML files can be quite complex and in order to simplify this complexity you split your config into several separate files and link them all together using either the <import /> tag or, depending upon your app, a ContextSingletonBeanFactoryLocator. Java based DI also allows you to split your @Configuration classes up and combine them in a logical way. And being quite helpful, the guys at Springsource give you several ways to do this.

    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class,
        AdditionalAppConfig.
class);

The code snippet above demonstrates that the constructor of the AnnotationConfigApplicationContext class takes a var-arg input list allowing you to load one or more @Configuration classes.

Another method of loading your configuration is to make use of the AnnotationConfigApplicationContext classes register(...) method. This is another var-arg method that you can call multiple times in your application:

  private static void usingRegister() {

   
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.register
(AppConfig.class);

   
// You can also register a list of config classes
    // ctx.register(AppConfig.class, OtherConfig.class);

    // You can call register multiple times register additional config classes
   
ctx.register(AdditionalAppConfig.class);

    ctx.refresh
();
    Interface_A serviceA = ctx.getBean
(Interface_A.class);
    serviceA.businessMethod
();
 
}

Most Spring developers are used to using the Spring <import /> tag and Springsource have provided a direct Java based equivalent that allows you to connect your @Configuration classes together, without the need for you to keep tabs on all your config classes.

The code snippets below demonstrate how this is done.

@Configuration
@Import
(AppConfig.class)
public class ImportExampleAppConfig {

 
/**
   * Factory method that creates a new Object_C
   *
   *
@return A new object
   */
 
@Bean
 
public Interface_C anotherInterfaceCService() {
   
return new Object_C();
 
}

}

This is really equivalent to:
<import resource="classpath:additional-app-config.xml"/>
The example above links two config classes together, but you can link multiple classes together using the following syntax:

@Import({AppConfig.class, AdditionalAppConfig.class})

The code for loading this context is as you would expect:

  private static void usingConfigImport() {

   
// Create the appropriate type of application context
   
ApplicationContext ctx = new AnnotationConfigApplicationContext(
       
ImportExampleAppConfig.class);

   
// Get the bean by type as there's only one
   
Interface_A serviceA = ctx.getBean(Interface_A.class);
   
// got the bean - so call our business method.
   
serviceA.businessMethod();

 
}

There are a whole host of other ways of creating your Spring context, including mixing XML and @Configuration classes and adding in auto-wiring - but more of that later.

No comments: