HomeToolsAbout

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 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.

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