Úvod do AutoFactory
1. Úvod
V tomto výučbe stručne predstavíme AutoFactoryod spoločnosti Google.
Toto je generátor kódu na zdrojovej úrovni, ktorý pomáha generovať továrne.
2. Nastavenie Maven
Skôr ako začneme, pridajme do súboru nasledujúcu závislosť pom.xml:
com.google.auto.factory auto-factory 1.0-beta5
Najnovšiu verziu nájdete tu.
3. Rýchly štart
Poďme sa teraz rýchlo pozrieť na to, čo AutoFactory môže robiť a vytvárať jednoduché Telefón trieda.
Takže, keď anotujeme Telefón trieda s @AutoFactory a jeho konštruktorový parameter s @ Za predpokladu, dostaneme:
@AutoFactory verejná trieda Telefón {private final Camera camera; súkromné finále String otherParts; PhoneAssembler (@Provided Camera camera, String otherParts) {this.camera = kamera; this.otherParts = otherParts; } // ...}
Použili sme iba dve anotácie: @AutoFactory a @ Za predpokladu. Keď potrebujeme továreň vygenerovanú pre našu triedu, môžeme ju anotovať @AutoFactory, keďže @ Za predpokladu sa vzťahuje na parametre konštruktora tejto triedy a znamená to, že anotovaný parameter by mal byť poskytnutý injected Poskytovateľ.
V úryvku vyššie očakávame fotoaparát poskytnúť akýkoľvek výrobca fotoaparátov a AutoFactory pomôže vygenerovať nasledujúci kód:
@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") verejná finálna trieda PhoneFactory {private final Provider cameraProvider; @Inject PhoneAssemblerFactory (poskytovateľ cameraProvider) {this.cameraProvider = checkNotNull (cameraProvider, 1); } PhoneAssembler create (String otherParts) {return new PhoneAssembler (checkNotNull (cameraProvider.get (), 1), checkNotNull (otherParts, 2)); } // ...}
Teraz máme PhoneFactory generované automaticky používateľom AutoFactory v čase kompilácie a môžeme ho použiť na vytvorenie inštancií telefónu:
PhoneFactory phoneFactory = nový PhoneFactory (() -> nová kamera („Neznáme“, „XXX“)); Telefón simplePhone = phoneFactory.create ("ďalšie časti");
The @AutoFactory anotáciu je možné použiť aj na konštruktérov:
verejná trieda ClassicPhone {súkromné finále String dialpad; súkromné záverečné Vyzváňanie strún; private String otherParts; @AutoFactory public ClassicPhone (@Provided String dialpad, @Provided String ringer) {this.dialpad = dialpad; this.ringer = zvonenie; } @AutoFactory public ClassicPhone (String otherParts) {this ("defaultDialPad", "defaultRinger"); this.otherParts = otherParts; } // ...}
V úryvku vyššie sme použili @AutoFactory obom konštruktérom. AutoFactory podľa toho pre nás jednoducho vygeneruje dve metódy vytvárania:
@Generated (value = "com.google.auto.factory.processor.AutoFactoryProcessor") verejná záverečná trieda ClassicPhoneFactory {súkromné konečné poskytovateľ java_lang_StringProvider; @Inject public ClassicPhoneFactory (poskytovateľ java_lang_StringProvider) {this.java_lang_StringProvider = checkNotNull (java_lang_StringProvider, 1); } verejné ClassicPhone create () {return new ClassicPhone (checkNotNull (java_lang_StringProvider.get (), 1), checkNotNull (java_lang_StringProvider.get (), 2)); } verejné ClassicPhone create (String otherParts) {vrátiť nový ClassicPhone (checkNotNull (otherParts, 1)); } // ...}
AutoFactory podporuje aj parametre anotované pomocou @ Za predpokladu, ale iba pre anotácie JSR-330.
Napríklad, ak chceme cameraProvider byť „Sony“, môžeme zmeniť Telefón trieda do:
@AutoFactory verejná trieda Telefón {PhoneAssembler (@Provided @Named ("Sony") Fotoaparát fotoaparátu, String otherParts) {this.camera = fotoaparát; this.otherParts = otherParts; } // ...}
AutoFactory si ponechá @ Menovaný@Qualifier aby sme to mohli využiť napríklad pri použití rámcov Dependency Injection:
@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") verejná finálna trieda PhoneFactory {private final Provider cameraProvider; @Inject PhoneAssemblerFactory (@Named ("Sony") Provider cameraProvider) {this.cameraProvider = checkNotNull (cameraProvider, 1); } // ...}
4. Prispôsobené generovanie kódu
Existuje niekoľko atribútov, ktoré môžeme použiť s @AutoFactory anotácia na prispôsobenie vygenerovaného kódu.
4.1. Názov vlastnej triedy
Názov vygenerovanej továrenskej triedy je možné nastaviť pomocou className:
@AutoFactory (className = "SamsungFactory") verejná trieda SmartPhone {// ...}
Pomocou konfigurácie vyššie vytvoríme triedu s názvom SamsungFactory:
@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") verejná finálna trieda SamsungFactory {// ...}
4.2. nefinančné Továrne
Upozorňujeme, že vygenerovaná továrenská trieda je predvolene označená ako konečná, takže toto správanie môžeme zmeniť nastavením hodnoty allowSubclasses atribút nepravda:
@AutoFactory (className = "SamsungFactory", allowSubclasses = true) verejná trieda SmartPhone {// ...}
Teraz máme:
@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") verejná trieda SamsungFactory {// ...}
4.3. Viac možností
Ďalej môžeme určiť zoznam rozhraní pre implementovanú generovanú továreň pomocou „implementujúci “parameter.
Tu potrebujeme SamsungFactory vyrábať smartfóny s prispôsobiteľným úložiskom:
verejné rozhranie CustomStorage {SmartPhone customROMInGB (int romSize); }
Upozorňujeme, že metódy v rozhraní by mali vracať inštancie základnej triedy SmartPhone.
Potom vygenerujte továrenskú triedu s implementovaným vyššie uvedeným rozhraním, AutoFactory vyžaduje príslušné konštruktory v základnej triede:
@AutoFactory (className = "SamsungFactory", allowSubclasses = true, implementation = CustomStorage.class) verejná trieda SmartPhone {verejná SmartPhone (int romSize) {// ...} // ...}
Teda AutoFactory vygeneruje nasledujúci kód:
@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") verejná trieda SamsungFactory implementuje CustomStorage {// ... public SmartPhone create (int romSize) {return new SmartPhone (romSize); } @Override public SmartPhone customROMInGB (int romSize) {return create (romSize); }}
4.4. Továrne s rozšíreniami
Odkedy AutoFactory môže generovať implementácie rozhraní, je prirodzené očakávať, že bude môcť rozšíriť aj triedy, a je to skutočne možné:
verejná abstraktná trieda AbstractFactory {abstrakt CustomPhone newInstance (značka String); } @AutoFactory (rozšírenie = AbstractFactory.class) verejná trieda CustomPhone {súkromná konečná značka reťazca; public CustomPhone (značka reťazca) {this.brand = značka; }}
Tu sme rozšírili AbstractFactory trieda pomocou predlžujúci sa. Tiež by sme mali všimnite si, že každá abstraktná metóda v základnej abstraktnej triede (AbstractFactory) by mal mať zodpovedajúci konštruktor v triede betónu (CustomPhone).
Nakoniec vidíme nasledujúci vygenerovaný kód:
@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") verejná finálna trieda CustomPhoneFactory rozširuje AbstractFactory {@Inject public CustomPhoneFactory () {} verejné CustomPhone create (značka reťazca) {vrátiť nový CustomPhone (checkNotNull (značka, 1)) ); } @Override public CustomPhone newInstance (String brand) {return create (brand); } // ...}
To vidíme AutoFactory je dostatočne inteligentný na to, aby využil konštruktor na implementáciu zodpovedajúcej abstraktnej metódy - skvelé vlastnosti, ako je táto v AutoFactory určite nám ušetrí veľa času a kódu.
5. AutoFactory S Guice
Ako sme už spomínali v tomto článku, AutoFactory podporuje anotácie JSR-330, takže doň môžeme integrovať existujúci rámec na vkladanie závislostí.
Najprv dodajme Guice do pom.xml:
com.google.inject guice 4.2.0
Najnovšia verzia servera Guice nájdete tu.
Teraz si ukážeme, ako dobre AutoFactory integruje sa do Guice.
Pretože očakávame, že spoločnosť „Sony“ bude poskytovateľom fotoaparátov, musíme vložiť a SonyCameraProvider do PhoneFactoryKonštruktér:
@Generated ("com.google.auto.factory.processor.AutoFactoryProcessor") verejná finálna trieda PhoneFactory {private final Provider cameraProvider; @Inject public PhoneFactory (@Named ("Sony") Provider cameraProvider) {this.cameraProvider = checkNotNull (cameraProvider, 1); } // ...}
Nakoniec urobíme väzbu v a Guice modul:
verejná trieda SonyCameraModule rozširuje AbstractModule {private static int SONY_CAMERA_SERIAL = 1; @Named ("Sony") @Provides Camera cameraProvider () {return new Camera ("Sony", String.format ("% 03d", SONY_CAMERA_SERIAL ++)); }}
Poskytovateľa fotoaparátu sme nastavili s poznámkami @Named („Sony“) v Modul SonyCamera tak, aby zodpovedala PhoneFactoryParameter konštruktora.
Teraz to vidíme Guice spravuje vkladanie závislostí pre našu vygenerovanú továreň:
Injector injector = Guice.createInjector (nový SonyCameraModule ()); PhoneFactory injectedFactory = injector.getInstance (PhoneFactory.class); Telefón xperia = injectedFactory.create ("Xperia");
6. Pod kapotou
Všetky anotácie poskytnuté používateľom AutoFactory sú spracovávané v štádiu kompilácie, ako sme si v článku podrobne vysvetlili: ako funguje spracovanie anotácií na úrovni zdroja.
7. Záver
V tomto článku sme si predstavili, ako používať AutoFactory a ako ju integrovať do Guice - továrne na písanie môžu byť opakujúce sa a náchylné na chyby - napríklad nástroje na generovanie kódu AutoFactory a AutoValue môže nám ušetriť veľa času a zbaviť nás jemných chýb.
Úplnú implementáciu vzorov kódu nájdete ako vždy na serveri Github.