Introduktion til Dagger 2

1. Introduktion

I denne vejledning ser vi på Dagger 2 - en hurtig og let afhængighedsinjektionsramme.

Rammen er tilgængelig for både Java og Android, men den høje ydeevne, der stammer fra indsamlingstid-indsprøjtning, gør det til en førende løsning for sidstnævnte.

2. Afhængighedsinjektion

Som en lidt påmindelse er Dependency Injection en konkret anvendelse af det mere generiske Inversion of Control-princip, hvor strømmen af ​​programmet styres af selve programmet.

Det implementeres gennem en ekstern komponent, der giver forekomster af objekter (eller afhængigheder), som andre objekter har brug for.

Og forskellige rammer implementerer afhængighedsinjektion på forskellige måder. Især er en af ​​de mest bemærkelsesværdige af disse forskelle, om injektionen sker ved kørselstid eller ved kompileringstid.

Kørselstid DI er normalt baseret på refleksion, som er enklere at bruge, men langsommere ved kørselstid. Et eksempel på en run-time DI-ramme er Spring.

Kompileringstid DI er derimod baseret på kodegenerering. Dette betyder, at alle tunge operationer udføres under kompilering. Kompileringstid DI tilføjer kompleksitet, men fungerer generelt hurtigere.

Dagger 2 falder ind under denne kategori.

3. Maven / Gradle-konfiguration

For at bruge Dagger i et projekt skal vi tilføje dolk afhængighed af vores pom.xml:

 com.google.dagger dolk 2.16 

Desuden skal vi også inkludere den Dagger-kompilator, der bruges til at konvertere vores kommenterede klasser til den kode, der bruges til injektionerne:

 org.apache.maven.plugins maven-compiler-plugin 3.6.1 com.google.dagger dolk-compiler 2.16 

Med denne konfiguration udsender Maven den genererede kode til mål / genererede kilder / annoteringer.

Af denne grund, vi er sandsynligvis nødt til at konfigurere vores IDE yderligere hvis vi vil bruge nogen af ​​dens kodefærdiggørelsesfunktioner. Nogle IDE'er har direkte understøttelse af annoteringsprocessorer, mens andre muligvis har brug for, at vi tilføjer denne mappe til build-stien.

Alternativt, hvis vi bruger Android med Gradle, kan vi inkludere begge afhængigheder:

kompiler 'com.google.dagger: dolk: 2.16' annotationProcessor 'com.google.dagger: dolk-compiler: 2.16'

Nu hvor vi har Dagger i vores projekt, lad os oprette en prøveapplikation for at se, hvordan det fungerer.

4. Implementering

For vores eksempel forsøger vi at bygge en bil ved at indsprøjte dens komponenter.

Nu, Dagger bruger standard JSR-330-kommentarerne mange steder, et væsen @Indsprøjte.

Vi kan tilføje kommentarerne til felter eller konstruktøren. Men siden Dagger understøtter ikke injektion på private marker, vi går til konstruktørinjektion for at bevare indkapsling:

offentlig klasse bil {privat motor motor; private mærke mærke; @Inject public Car (Motor motor, Brand brand) {this.motor = motor; this.brand = brand; } // getters og setters}

Dernæst implementerer vi koden for at udføre injektionen. Mere specifikt opretter vi:

  • -en modul, som er en klasse, der giver eller bygger objektenes afhængighed, og
  • -en komponent, som er en grænseflade, der bruges til at generere injektoren

Komplekse projekter kan indeholde flere moduler og komponenter, men da vi har et meget grundlæggende program at gøre, er en af ​​hver tilstrækkelig.

Lad os se, hvordan vi implementerer dem.

4.1. Modul

For at oprette et modul, vi er nødt til at kommentere klassen med @Module kommentar. Denne kommentar indikerer, at klassen kan gøre afhængigheder tilgængelige for containeren:

@Module public class VehiclesModule {}

Derefter, vi skal tilføje @Provides kommentar om metoder, der konstruerer vores afhængigheder:

@Module public class VehiclesModule {@Provides public Engine provideEngine () {return new Engine (); } @Provides @Singleton public Brand provideBrand () {return new Brand ("Baeldung"); }}

Bemærk også, at vi kan konfigurere omfanget af en given afhængighed. I dette tilfælde giver vi singleton rækkevidde til vores Mærke instans, så alle bilforekomsterne deler det samme mærkeobjekt.

4.2. Komponent

Når vi går videre, opretter vi vores komponentgrænseflade. Dette er den klasse, der vil generere bilforekomster, injicere afhængigheder leveret af VehiclesModule.

Kort sagt, vi har brug for en metodesignatur, der returnerer en Bil og vi er nødt til at markere klassen med @Komponent kommentar:

@Singleton @Component (moduler = VehiclesModule.class) offentlig grænseflade VehiclesComponent {Car buildCar (); }

Læg mærke til, hvordan vi bestod vores modulklasse som et argument til @Komponent kommentar. Hvis vi ikke gjorde det, ville Dagger ikke vide, hvordan man skulle bygge bilens afhængighed.

Da vores modul giver et enkelt objekt, skal vi også give det samme omfang til vores komponent, fordi Dolk tillader ikke, at uskoperede komponenter henviser til scoped-bindinger.

4.3. Kundekode

Endelig kan vi løbe mvn kompilere for at udløse annoteringsprocessorerne og generere injektorkoden.

Derefter finder vi vores komponentimplementering med samme navn som grænsefladen, lige foran "Dolk“:

@Test offentlig ugyldighed givenGeneratedComponent_whenBuildingCar_thenDependenciesInjected () {VehiclesComponent component = DaggerVehiclesComponent.create (); Car carOne = component.buildCar (); Car carTwo = component.buildCar (); Assert.assertNotNull (carOne); Assert.assertNotNull (carTwo); Assert.assertNotNull (carOne.getEngine ()); Assert.assertNotNull (carTwo.getEngine ()); Assert.assertNotNull (carOne.getBrand ()); Assert.assertNotNull (carTwo.getBrand ()); Assert.assertNotEquals (carOne.getEngine (), carTwo.getEngine ()); Assert.assertEquals (carOne.getBrand (), carTwo.getBrand ()); }

5. Analogier om foråret

De, der er fortrolige med Spring, har måske bemærket nogle paralleller mellem de to rammer.

Dolkens @Module annotation gør containeren opmærksom på en klasse på en meget lignende måde som enhver af Spring's stereotype annoteringer (for eksempel @Service, @Kontrol...). Ligeledes, @Provides og @Komponent svarer næsten til forårets @Bønne og @Kig op henholdsvis.

Foråret har også sin @Scope kommentar, der korrelerer med @Singleton, selvom bemærk her allerede en anden forskel i, at Spring antager som standard et singleton-omfang, mens Dagger standardindstiller det, som Spring-udviklere måske kalder prototype-omfanget, idet man påberåber sig udbydermetoden, hver gang der kræves en afhængighed.

6. Konklusion

I denne artikel gik vi igennem, hvordan man opsætter og bruger Dagger 2 med et grundlæggende eksempel. Vi overvejede også forskellene mellem kørselstid og indsamlingstid.

Som altid er al kode i artiklen tilgængelig på GitHub.