Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency...

21
University of Applied Sciences IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler Inversion of Control Containers and the Dependency Injection pattern http://martinfowler.com/articles/injection.html

Transcript of Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency...

Page 1: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

IoC Containers and the Dependency Injection pattern

Ausarbeitung des Artikels von Martin Fowler

Inversion of Control Containers and

the Dependency Injection pattern

http://martinfowler.com/articles/injection.html

Page 2: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

Inhaltsverzeichnis

IoC Containers and the Dependency Injection pattern

1. Martin Fowler 5. Service Locator vs Dependency Injection

2. Einleitung 6. Constructor vs Setter Injection

3. IoC / Dependency Injection 7. Fazit

3.1 Constructor Injection

3.2 Setter Injection

3.3 Interface Injection

4. Service Locator

4.1 Nutzung eines abgetrennten Interfaces

4.2 Dynamischer Service Locator

4.3 Nutzung von Locator und Injection

Page 3: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

1. Martin Fowler

IoC Containers and the Dependency Injection pattern

Martin Fowler ist Autor und renommierter Referent zum Thema Softwarearchitektur, spezialisiert auf objekt-orientierte Analyse und Design, UML, Entwurfsmuster und agile Softwareentwicklung.

Er schrieb fünf bedeutende Bücher zum Thema Softwareentwicklung.

Heute arbeitet er als Chefentwickler beim Consulting-Unternehmen ThoughtWorks.

Page 4: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

2. Einleitung

IoC Containers and the Dependency Injection pattern

Das generelle Problem ist die Art der Zusammenführung unterschiedlicher Elemente.

class MovieLister...

public Movie[] moviesDirectedBy(String arg) {

List allMovies = finder.findAll();

for (Iterator it = allMovies.iterator(); it.hasNext();) {

Movie movie = (Movie) it.next();

if (!movie.getDirector().equals(arg)) it.remove();

}

return (Movie[]) allMovies.toArray(newMovie[allMovies.size()]);

}

Beispiel:

MovieLister

Page 5: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

2. Einleitung

IoC Containers and the Dependency Injection pattern

Beispiel: MovieLister

public interface MovieFinder {

List findAll();

}

class MovieLister...

private MovieFinder finder;

public MovieLister() {

finder = new ColonDelimitedMovieFinder("movies1.txt");

}

Page 6: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

3. IoC / Dependency Injection

IoC Containers and the Dependency Injection pattern

Im vorherigen Beispiel hat der „lister“ die „finder“ Implementation durch direktes Ansprechen gefunden.

Dies unterscheidet den „finder“ vom Plugin.

Durch ein separates Assemblermodul soll die Implementation in den „lister“eingebunden werden.

Als Resultat vieler Diskussionen mit IoC Vertretern hat man sich auf den Namen „Dependency Injection” (Unabhängige Injizierung) geeinigt, da der Name IoC viel zu allgemein gehalten ist.

Page 7: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

3.1 Constructor Injection

IoC Containers and the Dependency Injection pattern

Am Beispiel: PicoContainer(Komponenten definieren)

class MovieLister...

public MovieLister(MovieFinder finder){

this.finder = finder;

}

class ColonMovieFinder...

public ColonMovieFinder(String filename) {

this.filename = filename;

}

Page 8: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

3.1 Constructor Injection

IoC Containers and the Dependency Injection pattern

Am Beispiel: PicoContainer (Konfigurieren)

private MutablePicoContainer configureContainer() {

//Erzeugung eines Pico Containers

MutablePicoContainer pico = new DefaultPicoContainer();

Parameter[] finderParams =

{new ConstantParameter ("movies1.txt")};

pico.registerComponentImplementation (MovieFinder.class, ColonMovieFinder.class, finderParams);

Registriert eine Klasse(2) unter einem bestimmten Key(1), Der Parameter(3) wird dann mit zum

Konstruktor übergeben (später)

pico.registerComponentImplementation(MovieLister.class);

Registriert eine Klasse(1) bei der von Bedarf ein Objekt erzeugt wird, mit sich selbst(1) als Key

return pico;

}

Page 9: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

3.1 Constructor Injection

IoC Containers and the Dependency Injection pattern

Am Beispiel: PicoContainer (Testen)

public void testWithPico() {

MutablePicoContainer pico = configureContainer(); siehe oben

MovieLister lister = (MovieLister) pico.getComponentInstance(MovieLister.class);

Holt sich eine Componente die unter diesem Schlüssel reg. wurde

Movie[] movies = lister.moviesDirectedBy("Sergio Leone");

assertEquals("Once Upon a Time in the West", movies[0].getTitle());

}

Page 10: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

3.2 Setter Injection

IoC Containers and the Dependency Injection pattern

Am Beispiel: Spring (Komponenten definieren)

class MovieLister...

private MovieFinder finder;

public void setFinder(MovieFinder finder) {

this.finder = finder;

}

class ColonMovieFinder...

public void setFilename(String filename) {

this.filename = filename;

}

Page 11: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

3.2 Setter Injection

IoC Containers and the Dependency Injection pattern

Am Beispiel: Spring (Konfigurieren)

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

Page 12: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

3.2 Setter Injection

IoC Containers and the Dependency Injection pattern

Am Beispiel: Spring (Testen)

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());

}

Page 13: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

3.3 Interface Injection

IoC Containers and the Dependency Injection pattern

Für alle set-Methoden (Setter-Injection) werden eigene Interfaces definiert.

Diese enthalten die Inject-Methoden:

public interface InjectFinder {

void injectFinder(MovieFinder finder);

}

class MovieLister implements InjectFinder{

public void injectFinder(MovieFinder finder) {

this.finder = finder;

}

}

Konfiguration hat zwei Ebenen: Die Registrierung der Komponenten

Die Registrierung der Injektoren

Page 14: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

4. Service Locator

IoC Containers and the Dependency Injection pattern

Die Grundidee hinter einem Service Locator besteht in einem Objekt, dass alle Dienste beschafft, die die Applikation benötigen könnte.

class MovieLister...MovieFinder finder = ServiceLocator.movieFinder();

class ServiceLocator...public static MovieFinder movieFinder() {

return soleInstance.movieFinder; } public static void load(ServiceLocator arg) {

soleInstance = arg; }public ServiceLocator(MovieFinder movieFinder) {

this.movieFinder = movieFinder;}

private static ServiceLocator soleInstance; private MovieFinder movieFinder;

Page 15: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

4. Service Locator

IoC Containers and the Dependency Injection pattern

Konfiguration und Test

class Tester... private void configure() {

ServiceLocator.load(new ServiceLocator(new ColonMovieFinder("movies1.txt"))); }

public void testSimple() { configure(); MovieLister lister = new MovieLister(); Movie[] movies = lister.moviesDirectedBy("Sergio Leone"); assertEquals("Once Upon a Time in the West",

movies[0].getTitle()); }

Page 16: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

4.1 Nutzung eines abgetrennten Interfaces

IoC Containers and the Dependency Injection pattern

Eins der Probleme des einfachen Ansatzes ist, dass der MovieLister abhängig von der kompletten ServiceLocator Klasse ist, obwohl er nur einen einzigen Dienst nutzt.

Man kann dieses Problem reduzieren, indem man ein Interface zwischen dem MovieLister und dem Service Locator schiebt.

Somit kann der lister nur einen Teil der Schnittstelle ansprechen, ohne die kompletteServiceLocator Schnittstelle zu nutzen.

Page 17: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

4.2 Dynamischer Service Locator

IoC Containers and the Dependency Injection pattern

Das vorherige Beispiel war statisch, da die ServiceLocator Klasse Methoden für jeden Dienst besaß, den sie benötigte.

Das ist aber nicht der einzige Weg. Man kann auch einen dynamischen ServiceLocatorerstellen, der einem erlaubt jeden Dienst, den man benötigen könnte, zu integrieren undwährend der Laufzeit auszuwählen.

Dazu benutzt der ServiceLocator eine HashMap, die die Services enthält. Sie bietet generische Methoden zum Erhalten und Laden der Dienste an.

Page 18: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

4.3 Nutzung von Locator und Injection

IoC Containers and the Dependency Injection pattern

Dependency Injection und Service Locator sind keine sich gegenseitig ausschließende Konzepte.

Beispiel:

public class MyMovieLister implements MovieLister, Serviceable { private MovieFinder finder;public void service(ServiceManager manager) {

finder = (MovieFinder)manager.lookup("finder");}

}

Die Service Methode ist ein Beispiel für Interface Injection, die dem Kontainer erlaubt einen ServiceManager in MyMovieLister zu injezieren.

Der ServiceManager ist ein Beispiel für einen Service Locator. Hier speichert der Lister den Manager nicht in einem Feld, stattdessen benutzt er ihn um den finder direkt zu speichern.

Page 19: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

5. Service Locator vs Dependency Injection

IoC Containers and the Dependency Injection pattern

- Beide Implementationen stellen das fundamentale Entkoppeln bereit,- Bei beiden ist der Applikations Code unabhängig von der konkreten Implementation

des Service interfaces.

Service Locator:- die Applikations Klasse fragt explizit den Locator- jeder Nutzer ist Abhängig vom Locator- um die Abhängigkeiten zu sehen, muss man den Code durchsuchen

Dependency Injection:- ss gibt keine explizite Anfrage, der Service erscheint in der Applikations Klasse

durch Inversion of Control- schwieriger zu debuggen- man sieht die Abhängigkeiten einfacher (Im Konstrukor oder bei den Set-Methoden)

Page 20: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

6. Constructor vs Setter Injection

IoC Containers and the Dependency Injection pattern

- Beide können sehr einfach Verbindungen zwischen Komponenten herstellen

Constructor:- jedes Objekt ist sofort verfügbar- geringfügig weniger Code - unveränderbare Felder können versteckt werden

Setter:- keine langen Argumentenlisten die unübersichtlich werden könnten - Setter bekommen eindeutige Namen - Konstruktoren werden nicht automatisch vererbt

Page 21: Inversion of Control Containers and the Dependency ... · IoC Containers and the Dependency Injection pattern Ausarbeitung des Artikels von Martin Fowler ... IoC Containers and the

University of Applied Sciences

11.12.2006 | Komponentenbasierte Softwareentwicklung | Dependency Injection | André Kley, Julian Päuler

7. Fazit

IoC Containers and the Dependency Injection pattern

Beim entwicklen von Anwendungsklassen sind Service Locator und DependencyInjection fast gleich. M.F. empfiehlt den Service Locator zu nutzen.

Es sei denn man entwickelt mehrere Klassen die in verschiedene Anwendungen laufen sollen.

Nutzt man Dependency Injection empfiehlt es sich mit der Constructor-Injection zu starten. Man sollte aber bereit sein auf Setter- Injection umzustellen, falls es zu gewissenProblemen kommt.