Google Guice Framework pentru injecție de dependență heise Developer

Cercetare în 2.336.843 Produse

guice

Google Earth și Maps sunt exemple ale spiritului inovator al gigantului motorului de căutare. Alte proiecte s-au dovedit în dezvoltarea internă a Google. Un membru tânăr al acestei familii este cadrul open source Guice, o alternativă slabă la Spring.

Google Guice, un cadru open source pentru injecția dependenței (DI), a fost creat în timpul extinderii aplicației de publicitate pe internet AdWords și a fost destinat să rezolve problemele legate de scalarea echipelor care apar în proiecte cu câteva sute de dezvoltatori. În ciuda cadrelor DI recunoscute, cum ar fi popularul Spring [1], Google a dorit să folosească propria sa variantă, în special ușoară, pentru dezvoltarea software-ului intern (a se vedea „Relația liberă”).

Genericele și adnotările din Java 5 sunt o parte esențială a cadrului [2]. În plus, Guice acceptă propriile domenii (vezi glosar), programarea orientată pe aspect (AOP) și integrarea Spring. Abilitatea de a injecta atribute statice, precum și gestionarea referințelor circulare completează imaginea.

Planificatorul accesează clasele specifice HotelBooking și MockBooking printr-o interfață de rezervare (Fig. 1).

Un exemplu în acest sens este o aplicație de planificare a vacanțelor care rezerva hoteluri (Figura 1). Obiectul planificator (apelant) adresează o rezervare a interfeței, în spatele căreia sunt ascunse implementări specifice (obiecte țintă). Pentru a nu fi necesar să interogați continuu sistemul țintă real în timpul dezvoltării, se folosește așa-numitul obiect fals (manechin). Dezvoltatorul ar trebui să poată trece cu ușurință la operațiuni productive.

Cadrul ar trebui să pară deosebit de slab și să reducă masiv „codul cazanului”. În loc să facă o muncă grea, dezvoltatorul ar trebui să se ocupe de esențial. În acest scop, Guice se concentrează exclusiv pe o implementare performantă a DI și a fost redusă în consecință, atât în ​​ceea ce privește dimensiunea fișierelor JAR, cât și consumul de memorie. Guice nu gestionează dependențele din fișierele XML centrale, ci le stochează în codul Java.

rezolva conflicte

Rezolvați conflictele cu Java

Experiența a arătat că dezvoltarea nu crește dacă prea mulți participanți concurează pentru accesul la componentele de bază. Conflictele urâte sunt inevitabile atunci când lucrați cu fișiere XML partajate. Editarea fișierelor Java este, de asemenea, mai ușoară și mai puțin predispusă la erori decât editarea fișierelor XML mari. Acest lucru face refactorizarea semnificativ mai ușoară și mai bine susținută de instrumente. Guice a trecut deja testul practic în AdWords. De asemenea, face parte din binecunoscutul framework web Struts 2, în care reprezintă elementul central al arhitecturii plug-in-ului. Guice poate efectua servicii utile în toate aplicațiile Java. Proiectele mari și cele care se concentrează exclusiv pe injectarea eficientă a dependenței beneficiază în special. Aici Guice își poate arăta punctele forte, cum ar fi subțire și cabluri fără XML (a se vedea „Bine cablat”).

Aplicația pentru planificarea vacanței este din nou folosită ca exemplu. Sarcina lui Guice este de a atribui planificatorului obiectul de rezervare specific dorit, pe care îl poate accesa prin intermediul interfeței. În cazul analizat, acesta ar trebui să fie obiectul MockBooking. Pentru a face acest lucru, trebuie clarificat ce se injectează unde. Prima parte a întrebării este răspunsă de către așa-numitul modul cu un „binder”, care împreună atribuie interfața implementării. Următorul fragment de cod formează un astfel de modul și folosește metoda bind () pentru a lega interfața Booking de clasa concretă MockBooking .

O adnotare @Inject în obiectul planificator are grijă de „unde”:

Adnotarea @Inject indică faptul că un obiect de tip Rezervare urmează să fie injectat folosind constructorul. Cadrul stăpânește injecția constructorului (ca în exemplu), precum și metoda și injecția de câmp. Aceasta înseamnă că Guice poate utiliza, de asemenea, orice metode adnotate sau le poate injecta direct într-un atribut:

Elementele injectabile sunt tipuri primitive, cum ar fi int sau char, precum și enumere și, în general, instanțe din orice clasă.

Scenariul de testare poate fi simplificat și mai mult prin lipsa modulului de planificare cu legarea acestuia și specificarea unei legări implicite în interfață utilizând adnotarea @ImplementedBy:

Odată ce dezvoltatorul a modelat dependențele, Guice poate începe să funcționeze. Se diferențiază între inițializare și runtime. Când aplicația pornește, bootstrapping-ul începe cu injectarea unui obiect rădăcină. Guice se ocupă de restul lucrării prin graficul dependenței și efectuând recursiv toate injecțiile ulterioare. Are loc o validare, care indică goluri sau erori. Folosirea acestuia este la fel de simplă ca în acest exemplu:

O parte din fiecare legare este un furnizor care furnizează instanțe ale clasei înregistrate. În anumite cazuri, poate fi util sau inevitabil să creați singuri obiecte și să nu lăsați acest lucru furnizorului standard intern. Dacă utilizați o bibliotecă terță parte, nu puteți introduce o adnotare @Inject acolo, de exemplu. Cu ajutorul unui furnizor personalizat, este încă posibil să efectuați legarea. Furnizorii personalizați permit, de asemenea, integrarea cu obiecte livrate prin JNDI sau JMX.

Injectorul ca element cheie

Nu vă fie teamă de injecții

Elementul cheie în structura Guice este injectorul, care gestionează legăturile (Figura 2). Aceștia din urmă utilizează adnotări pe ținta de injectare și se referă la un tip de injectat. Furnizorul creează instanțele de acest tip. Scopul unei legări este o specificație opțională și controlează refolosirea obiectelor generate și injectate. Pentru fiecare injecție, Guice creează de obicei o nouă instanță a obiectului în cauză. Domeniile alternative sunt „Singleton”, „Request” și „Session”.

În plus față de mecanismele de bază descrise, Guice cunoaște o serie de opțiuni suplimentare. Aceasta include definirea propriilor adnotări, care, de exemplu, permit o alocare suplimentară a rezervărilor de zboruri și închirieri auto.

Când auziți injecția de dependență sau inversiunea controlului, de obicei vă gândiți mai întâi la primăvară. Nu fără un motiv întemeiat, deoarece standardul de facto este cel care are în spate o comunitate activă. După cum sa menționat deja, în ciuda existenței sale, Google vede necesitatea unei soluții proprii. Alternative precum JBoss Seam, Apache HiveMind sau Pico-Container nu au împiedicat compania să se dezvolte intern.

Ambele cadre - Spring și Guice - aparțin produselor open source și se află sub licența Apache 2.0. Adnotările și genericele ca componente ale Guice permit utilizarea numai din Java 5. Acest lucru nu se aplică Spring, poate fi folosit chiar și cu JDK 1.3 și oferă semnificativ mai multe funcții decât Guice. În timp ce acesta din urmă se concentrează pe DI, Spring acceptă, de asemenea, tranzacțiile, persistența și are propriul său cadru web. Subproiecte există pentru configurare, securitate, lucrări în serie și câteva altele.

Definiția dependențelor dintre obiecte formează coloana vertebrală a unui cadru DI. Modul în care sunt stocate și evaluate dependențele (cablarea obiectelor) este o caracteristică caracteristică. Aceasta arată o altă diferență majoră între primăvară și Guice. Spring permite atât afișarea explicită, cât și cablarea automată. Guice adoptă o abordare diferită: Deși se bazează pe o reprezentare explicită, acesta ocolește formatul XML vorbitor încorporând relațiile în codul sursă folosind adnotări Java. Această procedură poate fi înțeleasă ca un amestec între afișajul detaliat, dar intensiv de întreținere, explicit și cablarea automată. Primăvara permite, de asemenea, crearea de dependențe în codul Java cu JavaConfig, dar acest subproiect este încă în starea de reper.

performanţă

Mic, rapid, clar

Guice prezintă avantajele sale de performanță față de Spring atât la pornirea aplicației, cât și la timpul de rulare atunci când vine vorba de crearea obiectelor solicitate. Guice atinge avantajul când creează obiecte prin capabilități simultane Java 5. (Cu toate acestea, ar trebui să se schimbe cu Spring 3, care se va baza în întregime pe Java 5.) În plus, nu generează obiectele proxy pe care Spring le folosește. Cu toate acestea, cât de relevant este acest lucru în practică, depinde de natura aplicației.

În plus față de proprietățile tehnice și gama de funcții, aspecte precum complexitatea sunt importante atunci când alegeți un instrument. Google îl vede în mod clar pe Guice cu un avantaj față de Spring în ceea ce privește simplitatea, claritatea, capacitatea de întreținere, capacitatea de învățare și performanța.

În general, numeroasele comparații ale celor două cadre au generat entuziasm în cercurile respective. În cele din urmă, totuși, nu se rezumă la o decizie sau, deoarece, deși ambele sunt containere DI, acestea au un accent diferit: Guice lasă o mică „amprentă”, în timp ce Spring se oferă ca o soluție cuprinzătoare și puternică. O mare parte din complexitatea sa XML rezultă și din funcții în afara DI. Deoarece Guice nu acoperă aceste zone, nu există o rivalitate reală. Coexistența ambelor cadre este concepută, deoarece Guice permite integrarea bobului de primăvară.

Planul pentru Guice 2 - planificat pentru ianuarie 2009 - conține o serie de îmbunătățiri, inclusiv ascultător de construcții și un API de introspecție. Ascultătorii oferă puncte de intrare atunci când creează obiecte pentru a-ți conecta propria logică. Extensia API este menită să expună elementele interne ale obiectului Injector și să permită accesul complet la graficul de dependență. Acest lucru ar oferi un punct de plecare pentru instrumentele de vizualizare, de exemplu. Foaia de parcurs numește, de asemenea, metodele furnizorului cu care clasele de module pot fi proiectate mai ușor. Furnizorii personalizați ar putea astfel realiza o legătură mai flexibilă, care este eficientă doar într-un anumit domeniu, de exemplu.

Concluzie

Nici un fulger în tigaie

Guice este încă nou, deci există puține aplicații productive în afara Google. Cadrul web Struts2 menționat anterior este cu siguranță o excepție. Cu toate acestea, fundalul Google și utilizarea programului AdWords vor asigura că Guice nu va ajunge ca un fulger în pan. Modulele terță parte care există acum sunt o indicație suplimentară în acest sens. Aceasta include componente care permit Guice să interacționeze cu Hibernate sau cu cadrul Ajax DWR.

Dezavantajul este că documentația proiectului este încă destul de clară. Numărul tot mai mare de rapoarte și instrucțiuni de experiență atenuează oarecum acest neajuns. Din punct de vedere arhitectural, trebuie să considerăm, de asemenea, că adnotările proprietare fac dificilă reutilizarea claselor în proiecte non-Guice. Guice este relativ ușor de învățat și introducerea acestuia - chiar și în proiecte existente. Un alt avantaj este că cadrul poate fi instalat pas cu pas.

Tobias Lütticke
lucrează ca arhitect de soluții într-un minister din Wellington, Noua Zeelandă.

Christian Meder
este arhitect senior la inovex GmbH din Pforzheim.

glosar

glosar

Codul cazanului: Schema repetitivă, dar necesară, cod F care nu descrie logica de afaceri.

Injector: Componentă care îndeplinește o dependență prin injectarea obiectului dorit.

Modul: Recipient pentru legături care definește ceea ce trebuie injectat.

Legare: Legătură între o interfață și implementarea acesteia.

Domeniu de aplicare: Domeniul de aplicare al unui obiect injectat (de exemplu, cerere, sesiune, singleton).

(Personalizat) Furnizor: Creează obiectele de injectat. În varianta „Personalizată” pentru conectarea individuală a componentelor care nu sunt aplicative.

Bootstrapping: Inițializarea Guice prin injectarea obiectului rădăcină pentru a declanșa cablarea automată. Acest lucru evită nevoia de a interoga din nou injectorul mai târziu pentru fiecare injecție.

Adnotări: Informații meta pe care dezvoltatorul le stochează în codul sursă al claselor Java cu un caracter „@” precedent.

Generice: Metode și clase care pot fi parametrizate cu parametri de tip.

Bine cablat

Bine cablat

Cablarea descrie modul în care cadrul gestionează dependențele dintre obiecte. Există două forme de bază: reprezentarea explicită în XML sau Java și evaluarea automată de către cadru în timp de execuție (cablare automată). Ambele variante pot fi evaluate. În cazul cablării automate, cadrul încearcă să înțeleagă relațiile dintre componentele în sine. Cu toate acestea, pe măsură ce complexitatea aplicației crește, acest lucru creează o problemă: performanța devine din ce în ce mai proastă.

Relație slăbită

Relație slăbită

Dependency Injection (DI) este un concept popular în dezvoltarea de software. Două dintre obiectivele principale: simplificarea reutilizării și întreținerii software-ului prin cuplarea vagă a componentelor și facilitarea testării.

Când un obiect A deține o referință la un obiect B, de obicei știe implementarea acestuia. Conceptul DI prevede că dependențele dintre apelantul A și obiectivele B adresate de acesta nu mai sunt stocate în A. Apelantul este informat doar atunci când este necesar, care implementare a obiectului țintă B trebuie să fie adresată în mod specific. Relația cu betonul B este „injectată” în A în acest scop. În calitate de apelant, A nu cunoaște obiectul țintă care trebuie utilizat până la injecția finală.

DI este o aplicație a paradigmei Inversion of Control (IoC), cunoscută și sub numele de Principiul Hollywood: Nu ne sunați, vă vom suna. În acest fel, injecția de dependență permite utilizarea a diferite scenarii de utilizare fără a fi nevoie să adaptați codul sursă al apelantului, de exemplu atunci când sunt adăugate noi implementări ale obiectelor țintă. Un exemplu comun al unui astfel de obiectiv suplimentar este un serviciu ca variantă simplificată a serviciului original în scopuri de testare. Dacă serviciul propriu-zis necesită o mulțime de resurse și rulează pentru o lungă perioadă de timp sau este disponibil numai în mediul productiv, implementarea ca obiect simulat (fictiv) permite testarea (mai rapidă).