Google Guice Dependency Injection Beispiel-Tutorial
Google Guice ist das Framework, um die Abhängigkeitsinjektion in Anwendungen zu automatisieren. Wir haben gelernt, wie wir die Abhängigkeitsinjektion in Anwendungen manuell implementieren können. Aber wenn die Anzahl der Klassen in einer Anwendung wächst, ist es besser, ein Framework zu verwenden, um diese Aufgabe zu automatisieren. Google Guice ist eines der führenden Frameworks, dessen Hauptaufgabe darin besteht, die automatische Implementierung der Abhängigkeitsinjektion bereitzustellen. Wir arbeiten mit demselben Beispiel aus dem letzten Beitrag und lernen, wie wir Google Guice verwenden können, um den Implementierungsprozess für die Abhängigkeitsinjektion zu automatisieren. Die Abhängigkeiten von Google Guice sind auf Maven Central verfügbar, daher können Sie für Maven-Projekte die folgende Abhängigkeit hinzufügen.
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
</dependency>
Wenn Sie eine einfache Java-Anwendung haben, können Sie die Jar-Datei von der Google Guice-Homepage auf Google Code herunterladen. Beachten Sie, dass Sie in diesem Fall auch die transitiven Abhängigkeiten im Klassenpfad haben müssen, sonst erhalten Sie eine Laufzeitausnahme. In meinem Beispiel habe ich ein Maven-Projekt, dessen Projektstruktur wie im folgenden Bild aussieht.
Schauen wir uns die einzelnen Komponenten nacheinander an.
Service-Klassen
package com.journaldev.di.services;
public interface MessageService {
boolean sendMessage(String msg, String receipient);
}
Das MessageService-Interface bietet den grundlegenden Vertrag für die Dienste.
package com.journaldev.di.services;
import javax.inject.Singleton;
//import com.google.inject.Singleton;
@Singleton
public class EmailService implements MessageService {
public boolean sendMessage(String msg, String receipient) {
//some fancy code to send email
System.out.println("Email Message sent to "+receipient+" with message="+msg);
return true;
}
}
EmailService ist eine der Implementierungen von MessageService. Beachten Sie, dass die Klasse mit der @Singleton-Annotation versehen ist. Da Dienstobjekte durch Injector-Klassen erstellt werden, wird diese Annotation verwendet, um sie wissen zu lassen, dass die Dienstklassen Singleton-Objekte sein sollen. Google Guice 3.0 fügte die Unterstützung für JSR-330 hinzu, und wir können Annotations aus den Paketen com.google.inject oder javax.inject verwenden. Nehmen wir an, wir haben eine weitere Dienstimplementierung, um Facebook-Nachrichten zu senden.
package com.journaldev.di.services;
import javax.inject.Singleton;
//import com.google.inject.Singleton;
@Singleton
public class FacebookService implements MessageService {
public boolean sendMessage(String msg, String receipient) {
//some complex code to send Facebook message
System.out.println("Message sent to Facebook user "+receipient+" with message="+msg);
return true;
}
}
Verbraucherklasse
Da wir in unserer Anwendung Abhängigkeitsinjektion implementieren, initialisieren wir die Dienstklasse nicht in der Anwendung. Google Guice unterstützt sowohl setter-basierte als auch konstruktorbasierte Abhängigkeitsinjektion. Unsere Anwendungsklasse, die den Dienst verwendet, sieht wie folgt aus.
package com.journaldev.di.consumer;
import javax.inject.Inject;
//import com.google.inject.Inject;
import com.journaldev.di.services.MessageService;
public class MyApplication {
private MessageService service;
// constructor based injector
// @Inject
// public MyApplication(MessageService svc){
// this.service=svc;
// }
//setter method injector
@Inject
public void setService(MessageService svc){
this.service=svc;
}
public boolean sendMessage(String msg, String rec){
//some business logic here
return service.sendMessage(msg, rec);
}
}
Beachten Sie, dass ich den Code für konstruktorbasierte Injektionen auskommentiert habe. Dies ist nützlich, wenn Ihre Anwendung andere Funktionen bietet, die kein Dienstklassenobjekt benötigen. Beachten Sie auch die @Injector-Annotation, die von Google Guice verwendet wird, um die Dienstimplementierungsklasse zu injizieren.
Service-Implementierung binden
Offensichtlich wird Google Guice nicht wissen, welchen Dienst es verwenden soll. Wir müssen ihn konfigurieren, indem wir die abstrakte Klasse AbstractModule erweitern und eine Implementierung für die Methode configure() bereitstellen.
package com.journaldev.di.injector;
import com.google.inject.AbstractModule;
import com.journaldev.di.services.EmailService;
import com.journaldev.di.services.FacebookService;
import com.journaldev.di.services.MessageService;
public class AppInjector extends AbstractModule {
@Override
protected void configure() {
//bind the service to implementation class
//bind(MessageService.class).to(EmailService.class);
//bind MessageService to Facebook Message implementation
bind(MessageService.class).to(FacebookService.class);
}
}
Wie Sie sehen können, können wir jede der Implementierungen an die Dienstklasse binden. Wenn wir beispielsweise zu EmailService wechseln möchten, müssten wir lediglich die Bindungen ändern.
Kundenanwendung
Unsere Einrichtung ist bereit. Schauen wir uns an, wie wir sie mit einer einfachen Java-Klasse verwenden können.
package com.journaldev.di.test;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.journaldev.di.consumer.MyApplication;
import com.journaldev.di.injector.AppInjector;
public class ClientApplication {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new AppInjector());
MyApplication app = injector.getInstance(MyApplication.class);
app.sendMessage("Hi Pankaj", "pankaj@abc.com");
}
}
Die Implementierung ist sehr einfach zu verstehen. Wir müssen ein Injector-Objekt mit der Methode createInjector() der Guice-Klasse erstellen, in der wir das Implementierungsobjekt unserer Injector-Klasse übergeben. Dann verwenden wir den Injector, um unsere Verbraucherklasse zu initialisieren. Wenn wir die obige Klasse ausführen, wird die folgende Ausgabe erzeugt:
Message sent to Facebook user pankaj@abc.com with message=Hi Pankaj
Wenn wir die Bindungen in der Klasse AppInjector auf EmailService ändern, wird die folgende Ausgabe erzeugt:
Email Message sent to pankaj@abc.com with message=Hi Pankaj
JUnit-Testfälle
Da wir die MyApplication-Klasse testen möchten, müssen wir keine tatsächliche Dienstimplementierung erstellen. Wir können eine einfache Mock-Service-Implementierungsklasse wie unten verwenden.
package com.journaldev.di.services;
public class MockMessageService implements MessageService{
public boolean sendMessage(String msg, String receipient) {
return true;
}
}
Meine JUnit 4-Testklasse sieht wie folgt aus:
package com.journaldev.di.test;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.journaldev.di.consumer.MyApplication;
import com.journaldev.di.services.MessageService;
import com.journaldev.di.services.MockMessageService;
public class MyApplicationTest {
private Injector injector;
@Before
public void setUp() throws Exception {
injector = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(MessageService.class).to(MockMessageService.class);
}
});
}
@After
public void tearDown() throws Exception {
injector = null;
}
@Test
public void test() {
MyApplication appTest = injector.getInstance(MyApplication.class);
Assert.assertEquals(true, appTest.sendMessage("Hi Pankaj", "pankaj@abc.com"));;
}
}
Beachten Sie, dass ich die MockMessageService-Klasse an MessageService binde, indem ich eine anonyme Klassenimplementierung von AbstractModule verwende. Dies wird in der setUp()-Methode durchgeführt, die vor den Testmethoden ausgeführt wird.
Google Guice Projekt herunterladen
Das war alles für das Google Guice Beispiel-Tutorial. Die Verwendung von Google Guice zur Implementierung der Abhängigkeitsinjektion in einer Anwendung ist sehr einfach und funktioniert hervorragend. Es wird in Google-APIs verwendet, daher können wir davon ausgehen, dass es sich um hochgetesteten und zuverlässigen Code handelt. Laden Sie das Projekt oben herunter und probieren Sie es aus, um mehr zu lernen.