Sunday, November 15, 2009

Pico

I'm reading "Dependency Injection Using Spring and Guice". My first project is to try DI with PicoContainer. The Java code comes from the Pico Container website; the build script is my own. The references of one class to another are satisfied by the container, that is no object other than the container has to construct another object. The ant build script is the first exhibit followed by the classes in alphabetical order.

Note that the container determines that the Juicer requires a Peelable and a Peeler as constructor arguments and the container satisfies that requirement without ant code or XML directing it to do so. Neat.

Dependency Injection was popularized mainly by the SpringFramework Inversion of Control container but first noted by Robert Martin in a 1996 article.
<project name="pico" default="run" basedir=".">
   <property name="src"     location="src/main/java"/> 
   <property name="test.src"    location="src/test/java"/>
   <property name="build"        location="build"/>
   <property name="build.classes"  location="build/main/classes"/>

 <path id="classpath">
   <pathelement location="${build.classes}"/>
   <pathelement location="/Users/greghelton/dev/bin/pico/picocontainer-2.9.jar"/>
 </path>

 <path id="test.classpath">
   <pathelement path="${classpath}"/>
   <pathelement location="/users/greghelton/dev/lib/junit/junit-4.6.jar"/>
   <pathelement path="${build.classes}"/>
   <pathelement path="${test.classes}"/>
 </path>

 <target name="clean">
   <delete dir="${build}"/>
 </target>
 
 <target name="init" depends="clean">
   <mkdir dir="${build.classes}"/>
   <mkdir dir="${test.classes}"/>
 </target>

 <target name="compile" depends="init">
   <javac srcdir="${src}" 
          destdir="${build.classes}" classpathref="classpath"/>
   <javac srcdir="${test.src}" destdir="${test.classes}">
   <classpath><path refid="classpath.path"/></classpath>
   </javac>
 </target>

 <target name="run" depends="compile">
   <java classname="App">
      <classpath><path refid="classpath"/></classpath>
   </java>
 </target>
</project>
import org.picocontainer.MutablePicoContainer; 
import org.picocontainer.DefaultPicoContainer;

public class App { 

  public static void main(String[] args) { 
    MutablePicoContainer pico = new DefaultPicoContainer();  
    pico.addComponent(Apple.class);  
    pico.addComponent(Juicer.class);  
    pico.addComponent(Peeler.class); 
  
    Juicer juicer = (Juicer) pico.getComponent(Juicer.class); 
    juicer.juice(); 
  } 
}
public class Apple implements Peelable {  
  public void peel() { 
  
  }  
}
public class Juicer {  
  private final Peelable peelable;  
  private final Peeler peeler;  

  public Juicer(Peelable peelable, Peeler peeler) {  
    this.peelable = peelable;  
    this.peeler = peeler;  
  }
 
  public void juice() {
    System.out.println("Juicing <" + peelable + "> <" + peeler + ">");
  }
}
public interface Peelable {  
   void peel();  
}
import org.picocontainer.Startable;

public class Peeler implements Startable {  
  private final Peelable peelable;  

  public Peeler(Peelable peelable) {  
    this.peelable = peelable;  
  }
  
  public void start() {  
    peelable.peel();  
  }

  public void stop() {  
  
  }  
}