HomeAbout

Dependency Injection

What is it

Dependency Injection and Service Locator both performs wiring of application.

  • wiring = connecting multiple parts together as a cohesive application.

Service = Component

  • Similarities
    • Both are used by foreign applications.
  • Differences
    • Component should be used locally.
    • Service will be remotely accessed/used.

Registry

  • A well-known object that other objects can use to find common objects and services.

What is Inversion of Control

What is a Control.

  • Think control flow of a program.

Inversion of Control means providing any kind of callback (via implements or controls reaction) instead of acting on it directly

  • Meaning, inverting/redirecting control flow to the external handler/controller.

What is Dependency Injection

Dependency Injection is a specific version of IoC that is focused on removing dependency from your code.

Dependency Injection depends upon abstractions and not depend upon concretions via passing/injecting concrete implementation to the abstraction as a parameter.

Classes should depend upon interfaces or abstract classes instead of concrete classes and functions.

e.g. PersistenceManager class depends on InvoicePersistence interface instead of the classes that implement that interface.

Illustration

In below example, the TextEditor class is directly dependent upon SpellChecker because it is instantiated inside the class definition.

public class TextEditor { private SpellChecker checker; public TextEditor() { this.checker = new SpellChecker(); } }

Applying the inversion, we are creating abstraction by passing the SpellChecker in the TextEditor's constructor signature.

  • Not initializing the dependency in the class definition.
public class TextEditor { private IocSpellChecker checker; public TextEditor(IocSpellChecker checker) { this.checker = checker; } }

Passing the actual implementation of SpellChecker would look like this:

SpellChecker sc = new SpellChecker(); // dependency TextEditor textEditor = new TextEditor(sc);

This allows TextEditor class to choose which SpellChecker implementation to use because the dependency is injected.

Injection Patterns

also see "service-locator" page

Constructor Injection

// injects the finder class MovieLister... public MovieLister(MovieFinder finder) { this.finder = finder; } // finder class ColonMovieFinder... public ColonMovieFinder(String filename) { this.filename = filename; } // injection container private MutablePicoContainer configureContainer() { MutablePicoContainer pico = new DefaultPicoContainer(); Parameter[] finderParams = {new ConstantParameter("movies1.txt")}; // register both containers to global pico.registerComponentImplementation(MovieFinder.class, ColonMovieFinder.class, finderParams); pico.registerComponentImplementation(MovieLister.class); return pico; } // test public void testWithPico() { // mock container MutablePicoContainer pico = configureContainer(); // calling the lister MovieLister lister = (MovieLister) pico.getComponentInstance(MovieLister.class); // calling the method on the service Movie[] movies = lister.moviesDirectedBy("Sergio Leone"); // test assertion assertEquals("Once Upon a Time in the West", movies[0].getTitle()); }

Setter Injection

// lister to accept injection by defining a setter method class MovieLister... private MovieFinder finder; public void setFinder(MovieFinder finder) { this.finder = finder; } // setter for filename class ColonMovieFinder... public void setFilename(String filename) { this.filename = filename; } // configuration <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> // test 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 Injection

// finder interface public interface InjectFinder { void injectFinder(MovieFinder finder); } // must be implemented by class that wants to use a finder (lister) class MovieLister implements InjectFinder { public void injectFinder(MovieFinder finder) { this.finder = finder; } } // injecting filename to finder implementation public interface InjectFinderFilename { void injectFilename (String filename); } class ColonMovieFinder implements MovieFinder, InjectFinderFilename... public void injectFilename(String filename) { this.filename = filename; } // configuration class Tester... private Container container; private void configureContainer() { container = new Container(); registerComponents(); registerInjectors(); container.start(); } // container registration class Tester... private void registerComponents() { container.registerComponent("MovieLister", MovieLister.class); container.registerComponent("MovieFinder", ColonMovieFinder.class); } // injector registration class Tester... private void registerInjectors() { container.registerInjector(InjectFinder.class, container.lookup("MovieFinder")); container.registerInjector(InjectFinderFilename.class, new FinderFilenameInjector()); } public interface Injector { public void inject(Object target); } // component implementing the injector itself (should we do this?) class ColonMovieFinder implements Injector... public void inject(Object target) { ((InjectFinder) target).injectFinder(this); } class Tester... public static class FinderFilenameInjector implements Injector { public void inject(Object target) { ((InjectFinderFilename)target).injectFilename("movies1.txt"); } } // corresponding test class Tester… public void testIface() { configureContainer(); MovieLister lister = (MovieLister)container.lookup("MovieLister"); Movie[] movies = lister.moviesDirectedBy("Sergio Leone"); assertEquals("Once Upon a Time in the West", movies[0].getTitle()); }
AboutContact