[JAVA] Verstehe die offizielle Probe Coffee of Dagger2

Über Dagger2, eine DI-Bibliothek für Java / Android, das offizielle Beispiel Kaffee-App Ich möchte den Mechanismus basierend auf (/ master / examples / simple / src / main / java / Coffee) erklären. Die Kaffee-App war jedoch etwas schwer zu verstehen ("@ Binds", "Lazy" usw.), sodass der unten beschriebene Code leicht geändert wurde. Dagger2 User Guide kann mit Wissen von oben bis Mitte verstanden werden (Singletons und Scoped Bindings).

Was versuchst du zu machen

In diesem Beispiel wird versucht, eine Instanz der CoffeeMaker-Klasse mit Dagger2 zu erstellen.

Die CoffeeMaker-Klasse weist die folgenden Abhängigkeiten auf.

image.png https://docs.google.com/presentation/d/1fby5VeGU9CN8zjw4lAb2QPPsKRxx6mSwCe9q7ECNSJQ/pub?start=false&loop=false&delayms=3000&slide=id.p

Das Auflösen dieser Abhängigkeit und das Abrufen einer CoffeeMaker-Instanz kann etwas schwierig sein.

Heater heater = new ElectricHeater();
Pump pump = new Thermosiphon(heater);
CoffeeMaker coffeeMaker = new CoffeeMaker(heater, pump).maker();
coffeeMaker.brew();

Mit Dagger2 sieht der obige Code folgendermaßen aus:

CoffeeMaker coffeeMaker = DaggerCoffeeShop.create().maker();
coffeeMaker.brew();

Auf diese Weise wird der CoffeeMaker-Clientcode von der Komplexität beim Erstellen von Abhängigkeiten befreit. Im Folgenden wird beschrieben, wie Dagger2 diese Abhängigkeiten erstellt.

Abhängigkeitserklärung

Dagger verwendet einen Konstruktor mit der Annotation "@ Inject", um eine Instanz zu erstellen.

class Thermosiphon implements Pump {
    private final Heater heater;

    @Inject
    Thermosiphon(Heater heater) {
        this.heater = heater;
    }

    @Override
    public void pump() {
        if (heater.isHot()) {
            System.out.println("=> => pumping => =>");
        }
    }
}

Wenn eine Thermosiphon-Instanz angefordert wird, wird mit dem obigen Konstruktor eine Thermosiphon-Instanz erstellt.

Hier hängt die Thermosiphon-Klasse von der Heizklasse ab. Dolch identifiziert die im Konstruktor definierten Abhängigkeiten und löst sie auf.

Abhängigkeiten erfüllen

Dagger versucht, die Abhängigkeit zu erfüllen, indem er eine Instanz des angeforderten Typs erstellt, aber die Abhängigkeitserklärung von @ Inject funktioniert nicht immer. In den folgenden Fällen funktioniert "@ Inject" nicht.

--Type ist eine Schnittstelle Klassen der 3. Partei können nicht kommentiert werden

In der Kaffee-App werden die Typen, von denen CoffeeMaker abhängt (Heizung und Pumpe), als Schnittstellen deklariert, was oben der Fall ist. In diesen Fällen erstellt die mit "@ Provides" kommentierte Methode eine Instanz.

Beispielsweise deklariert Heater eine Abhängigkeit wie folgt: Definieren Sie eine mit "@ Provides" versehene Methode und geben Sie "Heater" als Rückgabetyp an.

@Provides
static Heater provideHeater() {
    return new ElectricHeater();
}

In ähnlicher Weise erklärt Thermosiphon: Die Methode "@ Provides" kann eigene Abhängigkeiten haben.

@Provides
static Pump providePump(Thermosiphon pump) {
    return pump;
}

Die Methode "@ Provides" muss zum Modul gehören. Ein Modul ist eine Klasse mit der Annotation "@ Module".

@Module
class DripCoffeeModule {
    @Provides
    static Heater provideHeater() {
        return new ElectricHeater();
    }

    @Provides
    static Pump providePump(Thermosiphon pump) {
        return pump;
    }
}

Konventionell scheint die Methode "@ Provides" ein Bereitstellungspräfix zu haben, und das Modul hat ein Modulsuffix.

Erstellen Sie ein Abhängigkeitsdiagramm

Klassen und Methoden, die durch "@ Inject" und "@ Provides" definiert sind, bilden einen Abhängigkeitsgraphen eines Objekts. Definieren Sie eine Komponente, um dieses Diagramm zu erstellen. Eine Komponente ist eine mit @ Component annotierte Schnittstelle und verfügt über Methoden ohne Argumente. Der Rückgabetyp dieser Methoden ist der Typ, den Sie auflösen möchten.

Im Folgenden wird eine CoffeeShop-Komponente mit einer Methode definiert, die eine CoffeeMaker-Instanz zurückgibt. Übergeben Sie das Modul an die Komponente, um die Abhängigkeiten darunter zu erstellen. Hier passieren wir das DripCoffeeModule.

@Component(modules = DripCoffeeModule.class)
interface CoffeeShop {
    CoffeeMaker maker();
}

Dagger generiert basierend auf dieser Definition automatisch eine Implementierung von CoffeeShop. Der von Dagger generierten Implementierungsklasse wird Dagger vorangestellt. Hier wird eine Implementierungsklasse namens DaggerCoffeeShop generiert.

Die Komponentenimplementierungsklasse verfügt über eine Builder-Methode, mit der Abhängigkeiten erstellt werden.

CoffeeShop coffeeShop = DaggerCoffeeShop.builder()
    .dripCoffeeModule(new DripCoffeeModule())
    .build();

Im obigen Beispiel wird eine DripCoffeeModule-Instanz manuell erstellt und an den Builder übergeben. Wenn jedoch die folgenden Bedingungen erfüllt sind, ist dieser Vorgang nicht erforderlich.

Wenn für Komponenten alle folgenden Module auf die oben genannten zutreffen, verfügt die Implementierungsklasse über eine Erstellungsmethode, mit der Sie eine Instanz direkt erstellen können, ohne den Builder durchlaufen zu müssen.

CoffeeShop coffeeShop = DaggerCoffeeShop.create();

Schließlich sieht der CoffeeMaker-Clientcode folgendermaßen aus:

CoffeeMaker coffeeMaker = DaggerCoffeeShop.create().maker();
coffeeMaker.brew();

Kaffee-App-Code (modifizierte Version)

Hier ist der Code mit einer geringfügigen Änderung der offiziellen Kaffee-App. Es wird nur mit den Funktionen in dem oben erläuterten Bereich implementiert.

** * Nur die Annotation "@ Singleton" wird später beschrieben. ** **.

Heater.java(Bleib offiziell)


interface Heater {
    void on();
    void off();
    boolean isHot();
}

Pump.java(Bleib offiziell)


interface Pump {
    void pump();
}

ElectricHeater(Bleib offiziell)


class ElectricHeater implements Heater {
    boolean heating;

    @Override
    public void on() {
        System.out.println("~ ~ ~ heating ~ ~ ~");
        this.heating = true;
    }

    @Override
    public void off() {
        this.heating = false;
    }

    @Override
    public boolean isHot() {
        return heating;
    }
}

Thermosiphon(Bleib offiziell)


class Thermosiphon implements Pump {
    private final Heater heater;

    @Inject
    Thermosiphon(Heater heater) {
        this.heater = heater;
    }

    @Override
    public void pump() {
        if (heater.isHot()) {
            System.out.println("=> => pumping => =>");
        }
    }
}

DripCoffeeModule.java


@Module
class DripCoffeeModule {
    @Singleton
    @Provides
    static Heater provideHeater() {
        return new ElectricHeater();
    }

    @Provides
    static Pump providePump(Thermosiphon pump) {
        return pump;
    }
}

CoffeeMaker(Bleib offiziell)


class CoffeeMaker {
    private final Heater heater;
    private final Pump pump;

    @Inject
    CoffeeMaker(Heater heater, Pump pump) {
        this.heater = heater;
        this.pump = pump;
    }

    public void brew() {
        heater.on();
        pump.pump();
        System.out.println(" [_]P coffee![_]P ");
        heater.off();
    }
}

CoffeeShop.java


@Singleton
@Component(modules = DripCoffeeModule.class)
public interface CoffeeShop {
    CoffeeMaker maker();
}

CoffeeApp.java


public class CoffeeApp {
     public static void main(String[] args) {
          CoffeeMaker coffeeMaker = DaggerCoffeeShop.create().maker();
          coffeeMaker.brew();
     }
}

@ Singleton Annotation

Beim Auflösen von Abhängigkeiten versucht Dagger jedes Mal, wenn dies standardmäßig angefordert wird, eine Instanz des Typs zu erstellen. Bei der Kaffee-App funktioniert das Standardverhalten jedoch nicht wie beabsichtigt.

Die Brühmethode von CoffeeMaker besteht darin, die Heizung einzuschalten (heater.on ()), Wasser zu gießen (pump.pump ()), Kaffee zu brühen (println ()) und die Heizung wieder auszuschalten. Gießen Sie Wasser nur, wenn die Heizung eingeschaltet ist. Das Überprüfen, ob die Heizung eingeschaltet ist, wird an die von der Pump-Instanz gehaltene Heat-Instanz delegiert. Zu diesem Zeitpunkt sind es jedoch die von der CoffeeMaker-Instanz gehaltene Heat-Instanz und die von der Pump-Instanz gehaltene Heat-Instanz Sie müssen sich auf dasselbe beziehen.

Wie oben erwähnt, wird Dolch jedes Mal erstellt, wenn ein Typ angefordert wird, sodass er sich nicht wie beabsichtigt verhält. Sie können dann die Annotation "@ Singleton" verwenden, um anzugeben, dass immer dieselbe Instanz zurückgegeben werden soll, wenn der Typ angefordert wird.

Im obigen Code ist die requireHeater-Methode von DripCoffeeModule mit "@ Singleton" versehen, um anzugeben, dass die Heater-Instanz Singleton ist. Die CoffeeShop-Oberfläche ist auch mit "@ Singleton" versehen, sodass die Komponente und ihre untergeordneten Instanzen denselben Lebenszyklus haben.

Zusammenfassung

Ich erklärte den grundlegenden Teil, der der erste Schritt ist, um Dolch zu verstehen. Da dies nur der erste Teil des Benutzerhandbuchs ist, denke ich, dass es noch viel Wissen gibt, das nicht ausreicht, um Dagger zu üben, sondern diejenigen, die Dagger von nun an verwenden möchten, und einige Tage später mein eigenes. Ich dachte, es wäre hilfreich für dich.

Recommended Posts

Verstehe die offizielle Probe Coffee of Dagger2
Lesen Sie die offizielle Dagger2-Dokumentation, um die Grundlagen zu verstehen
Verstehen Sie den grundlegenden Mechanismus von log4j2.xml
Verstehen Sie die Grundlagen von Android Audio Record
Zellers Beamter (fragt nach dem Tag)
Über den offiziellen Startleitfaden für Spring Framework
Der offizielle Name von Spring MVC ist Spring Web MVC
[Für Anfänger] Verstehen Sie schnell die Grundlagen von Java 8 Lambda
Verstehen Sie die Eigenschaften von Scala in 5 Minuten (Einführung in Scala)
Ich habe ein Sequenzdiagramm des j.u.c.Flow-Beispiels geschrieben
Die Welt der Clara-Regeln (2)
Beurteilung des Kalenders
Die Welt der Clara-Regeln (4)
Die Welt der Clara-Regeln (1)
Lassen Sie uns die Funktion verstehen!
Die Welt der Clara-Regeln (3)
Die Welt der Clara-Regeln (5)
Die Idee der schnellen Sortierung
Die Idee von jQuery
Befolgen Sie das Memorandum zur Funktionszuordnung (verstehen Sie die Beschreibung des Benutzermodells).