Pages

Tuesday, June 14, 2011

Three IoC frameworks with JSR-330 annotations

So this post - is very simple illustration of how to make a dependency-injected application with one of three options:
All of them have slightly different goals, but in some ways all of them can handle beans annotated with the annotations from the JSR-330 (Dependency Injection for Java) standardization effort.

So, no more jabber, here is the code for the one bean:

package com.sopovs.moradanen.ioctest;

import javax.inject.Inject;
import javax.inject.Named;

//@Named annotation is used only by Spring. Actually it is used not for its main 
//purpose (to give a name to the bean), but simply as an analog of the @Component Spring annotation  
@Named
public class MainBean {
 @Inject
 private DependencyBean dep;

 public void requestDep() {
  dep.doSmth();
 }
}

Another bean:

package com.sopovs.moradanen.ioctest;

import javax.inject.Named;

@Named
public class DependencyBean {
 public void doSmth() {
  System.out.println("Hello!");
 }
}

And their usage:

package com.sopovs.moradanen.ioctest;

import javax.inject.Inject;

import org.picocontainer.DefaultPicoContainer;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.injectors.AnnotatedFieldInjection;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;

public class Main {
 public static void main(String[] args) {
  // Spring
  ApplicationContext appConext = new AnnotationConfigApplicationContext("com.sopovs.moradanen.ioctest");
  System.out.println("Invoking from Spring");
  appConext.getBean(MainBean.class).requestDep();

  // Guice
  Injector injector = Guice.createInjector(new Module() {
   @Override
   public void configure(Binder binder) {
    binder.bind(MainBean.class);
    binder.bind(DependencyBean.class);
   }
  });
  System.out.println("Invoking from Guice");
  injector.getInstance(MainBean.class).requestDep();

  // PicoContainer
  MutablePicoContainer pico = new DefaultPicoContainer(new AnnotatedFieldInjection(Inject.class));
  pico.addComponent(MainBean.class);
  pico.addComponent(DependencyBean.class);
  System.out.println("Invoking from Pico");
  pico.getComponent(MainBean.class).requestDep();
 }
}
The maven project to not puzzle reader with what exact jars from these libraries should be added to the classpath is available on Github: https://github.com/isopov/ioc-test

The power of any of these frameworks cannot be seen here, but this post may be a starting point for comparison or investigation of one of the frameworks if such simple use case can ever be a problem to build.

However some properties are seen here:
  • Spring uses either xml configuration, or annotation-based configuration, or a mixture of them. Both are not very good for those how want to ensure that all is right without running application, despite the effort to provide such possibility.
  • Guice uses java-based configs receiving bonuses from compile-time checking for correctness.
  • PicoContainer - is very lightweight (actually Spring and Guice are very modular now and can be lightweight too), originally intended to be used with constructor injection, but now supporting method and field injection too. And PicoContainer site is a good source of general knowledge about dependency injection. Also PicoContainer does not support cyclic injection of dependencies (if DependencyBean will have a field of MainBean).

3 comments:

  1. This is all very interesting, but how do you do the DI where the client does not need to use any Spring/Guice/Pico code and the DI environment is set up separately to show how a DI provider can be swapped out at runtime? TIA

    ReplyDelete
  2. I don't actually understand the question.

    If you need to reuse classes in the environment without DI - don't use annotations. XMLs with Srping, or a bit more verbose java-code handling DI in Guice will be fine.

    ReplyDelete
  3. > Spring uses either xml configuration, or annotation-based configuration
    Spring has for a long time supported Java-based configuration too (which you can mix and match with the other two modes if desired), see http://docs.spring.io/spring/docs/3.0.x/reference/beans.html#beans-java

    ReplyDelete