Introduksjon til AutoFactory

1. Introduksjon

I denne opplæringen vil vi gi en kort introduksjon til Autofabrikk, fra av Google.

Dette er en kildegenerator på kildenivå som hjelper til med å generere fabrikker.

2. Maven-oppsett

Før vi begynner, la oss legge til følgende avhengighet til pom.xml:

 com.google.auto.factory auto-factory 1.0-beta5 

Den siste versjonen finner du her.

3. Hurtigstart

La oss nå ta en rask titt på hva Autofabrikk kan gjøre og lage en enkel Telefon klasse.

Så når vi kommenterer Telefon klasse med @AutoFactory og dens konstruktørparameter med @Sørget for, vi får:

@ AutoFactory offentlig klasse Telefon {privat slutt Kamera kamera; privat finale String otherParts; PhoneAssembler (@Provided Camera camera, String otherParts) {this.camera = kamera; this.otherParts = otherParts; } // ...}

Vi brukte bare to merknader: @AutoFactory og @Sørget for. Når vi trenger en fabrikk generert for klassen vår, kan vi kommentere den med @AutoFactory, mens @Sørget for gjelder konstruktorparametere i denne klassen, og det betyr at den merkede parameteren skal leveres av en injisert Forsørger.

I utdraget over forventer vi at Kamera skal leveres av enhver kameraprodusent og Autofabrikk vil bidra til å generere følgende kode:

@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") offentlig sluttklasse PhoneFactory {privat sluttleverandør cameraProvider; @Inject PhoneAssemblerFactory (Provider cameraProvider) {this.cameraProvider = checkNotNull (cameraProvider, 1); } PhoneAssembler create (String otherParts) {return new PhoneAssembler (checkNotNull (cameraProvider.get (), 1), checkNotNull (otherParts, 2)); } // ...}

Nå har vi en Telefonfabrikk genereres automatisk av Autofabrikk på kompileringstidspunktet, og vi kan bruke den til å produsere telefonforekomster:

PhoneFactory phoneFactory = ny PhoneFactory (() -> nytt kamera ("Ukjent", "XXX")); Telefon simplePhone = phoneFactory.create ("andre deler");

De @AutoFactory merknader kan også brukes på konstruktører:

offentlig klasse ClassicPhone {privat slutt String-tastatur; privat finale String ringetone; private String andreDeler; @ AutoFactory offentlig ClassicPhone (@Provided String dialpad, @Provided String ringer) {this.dialpad = dialpad; this.ringer = ringetone; } @ AutoFactory offentlig ClassicPhone (String otherParts) {dette ("defaultDialPad", "defaultRinger"); this.otherParts = otherParts; } // ...}

I utdraget over søkte vi @AutoFactory til begge konstruktørene. Autofabrikk vil ganske enkelt generere to opprettelsesmetoder for oss tilsvarende:

@Generated (value = "com.google.auto.factory.processor.AutoFactoryProcessor") offentlig endelig klasse ClassicPhoneFactory {privat sluttleverandør java_lang_StringProvider; @Inject public ClassicPhoneFactory (Provider java_lang_StringProvider) {this.java_lang_StringProvider = checkNotNull (java_lang_StringProvider, 1); } public ClassicPhone create () {return new ClassicPhone (checkNotNull (java_lang_StringProvider.get (), 1), checkNotNull (java_lang_StringProvider.get (), 2)); } public ClassicPhone create (String otherParts) {return new ClassicPhone (checkNotNull (otherParts, 1)); } // ...}

Autofabrikk støtter også parametere merket med @Sørget for, men bare for JSR-330-merknader.

For eksempel hvis vi vil ha cameraProvider å være “Sony”, kan vi endre Telefon klasse til:

@AutoFactory offentlig klasse Telefon {PhoneAssembler (@Provided @Named ("Sony") Kamerakamera, String andre deler) {this.camera = kamera; this.otherParts = otherParts; } // ...}

AutoFactory beholder @Named@Kvalifiserende slik at vi kan bruke det, for eksempel når vi bruker avhengighetsinjeksjonsrammer:

@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") offentlig sluttklasse PhoneFactory {privat sluttleverandør cameraProvider; @Inject PhoneAssemblerFactory (@Named ("Sony") Provider cameraProvider) {this.cameraProvider = checkNotNull (cameraProvider, 1); } // ...}

4. Tilpasset kodegenerering

Det er flere attributter vi kan bruke med @AutoFactory kommentar for å tilpasse den genererte koden.

4.1. Tilpasset klassenavn

Navnet på den genererte fabrikklassen kan angis med klassenavn:

@AutoFactory (className = "SamsungFactory") SmartPhone med offentlig klasse {// ...}

Med konfigurasjonen ovenfor oppretter vi en klasse med navnet SamsungFactory:

@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") offentlig sluttklasse SamsungFactory {// ...}

4.2. ikke-endelig Fabrikker

Merk at den genererte fabrikklassen er merket som standard som standard, så vi kan endre denne oppførselen ved å sette allowSubclasses tilskrive falsk:

@AutoFactory (className = "SamsungFactory", allowSubclasses = true) SmartPhone i offentlig klasse {// ...}

Nå har vi:

@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") offentlig klasse SamsungFactory {// ...}

4.3. Flere evner

I tillegg kan vi spesifisere en liste over grensesnitt for den genererte fabrikken som skal implementeres ved hjelp av “implementere ”parameter.

Her trenger vi SamsungFactory å produsere smarttelefoner med tilpassbar lagring:

offentlig grensesnitt CustomStorage {SmartPhone customROMInGB (int romSize); }

Merk at metoder i grensesnittet skal returnere forekomster av basisklassen SmartPhone.

For å generere en fabrikklasse med grensesnittet ovenfor implementert, Autofabrikk krever relevante konstruktører i basisklassen:

@AutoFactory (className = "SamsungFactory", allowSubclasses = true, implementering = CustomStorage.class) offentlig klasse SmartPhone {offentlig SmartPhone (int romSize) {// ...} // ...}

Og dermed, Autofabrikk vil generere følgende kode:

@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") offentlig klasse SamsungFactory implementerer CustomStorage {// ... public SmartPhone create (int romSize) {returner ny SmartPhone (romSize); } @ Overstyr offentlig SmartPhone customROMInGB (int romSize) {return create (romSize); }}

4.4. Fabrikker med utvidelser

Siden Autofabrikk kan generere grensesnittimplementeringer, er det naturlig å forvente at det også kan utvide klasser, og dette er faktisk mulig:

offentlig abstrakt klasse AbstractFactory {abstrakt CustomPhone newInstance (String merkevare); } @AutoFactory (utvidende = AbstractFactory.class) offentlig klasse CustomPhone {privat final String merkevare; offentlig CustomPhone (strengmerke) {this.brand = merkevare; }}

Her utvidet vi AbstraktFabrikk klasse bruker utvide. Vi burde også Vær oppmerksom på at hver abstrakte metode i grunnleggende abstraktklasse (AbstraktFabrikk) skal ha en tilsvarende konstruktør i betongklassen (CustomPhone).

Til slutt kan vi se følgende genererte kode:

@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") offentlig sluttklasse CustomPhoneFactory utvider AbstractFactory {@Inject public CustomPhoneFactory () {} public CustomPhone create (String brand) {return new CustomPhone (checkNotNull (brand, 1) ); } @ Override offentlig CustomPhone newInstance (strengmerke) {return create (brand); } // ...}

Vi kan se det Autofabrikk er smart nok til å bruke konstruktøren til å implementere den tilsvarende abstrakte metoden - flotte funksjoner som dette i Autofabrikk vil sikkert spare oss mye tid og kode.

5. Autofabrikk Med Guice

Som vi nevnte tidligere i denne artikkelen, Autofabrikk støtter JSR-330-merknader, slik at vi kan integrere eksisterende avhengighetsinjeksjonsrammer med det.

La oss først legge til Guice til pom.xml:

 com.google.inject guice 4.2.0 

Den siste versjonen av Guice finner du her.

Nå skal vi demonstrere hvor godt Autofabrikk integreres med Guice.

Ettersom vi forventer at “Sony” er kameraleverandøren, må vi injisere en SonyCameraProvider til Telefonfabrikk’S konstruktør:

@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") offentlig sluttklasse PhoneFactory {privat sluttleverandør cameraProvider; @Inject public PhoneFactory (@Named ("Sony") Provider cameraProvider) {this.cameraProvider = checkNotNull (cameraProvider, 1); } // ...}

Til slutt lager vi bindingen i a Guice modul:

offentlig klasse SonyCameraModule utvider AbstractModule {privat statisk int SONY_CAMERA_SERIAL = 1; @Named ("Sony") @Provides Camera cameraProvider () {returner nytt kamera ("Sony", String.format ("% 03d", SONY_CAMERA_SERIAL ++)); }}

Og vi setter kameraleverandøren med kommentarer @Named (“Sony”) i SonyCameraModule å passe sammen Telefonfabrikk’S konstruktørparameter.

Nå kan vi se det Guice administrerer avhengighetsinjeksjon for vår genererte fabrikk:

Injektorinjektor = Guice.createInjector (ny SonyCameraModule ()); PhoneFactory injectedFactory = injector.getInstance (PhoneFactory.class); Phone xperia = injectedFactory.create ("Xperia");

6. Under panseret

Alle merknader levert av Autofabrikk blir behandlet i kompileringsfasen, som vi har forklart i detalj i artikkelen: hvordan behandling av merknader på kildenivå fungerer.

7. Konklusjon

I denne artikkelen har vi introdusert hvordan du bruker AutoFactory, og hvordan du integrerer den med Guice - å skrive fabrikker kan være repeterende og feilutsatt - kodegenereringsverktøy som Autofabrikk og Autoverdi kan spare oss for mye tid og frigjøre oss fra subtile feil.

Som alltid kan full implementering av kodeeksemplene finnes på Github.


$config[zx-auto] not found$config[zx-overlay] not found