Vodič za Google Guice

1. Uvod

Ovaj članak će ispitati osnovama Google Guicea. Razmotrit ćemo pristupe izvršavanju osnovnih zadataka ubrizgavanja ovisnosti (DI) u Guiceu.

Također ćemo usporediti i usporediti Guiceov pristup s onim uspostavljenijim DI okvirima kao što su Spring i Contexts and Dependency Injection (CDI).

Ovaj članak pretpostavlja da čitatelj razumije razumijevanje uzoraka ubrizgavanja ovisnosti.

2. Postavljanje

Da biste koristili Google Guice u svom projektu Maven, morat ćete dodati sljedeću ovisnost u svoj pom.xml:

 com.google.inject guice 4.1.0 

Ovdje postoji i zbirka proširenja Guice (ona ćemo obraditi nešto kasnije), kao i moduli nezavisnih proizvođača za proširenje mogućnosti Guicea (uglavnom pružanjem integracije u ustaljenije Java okvire).

3. Ubrizgavanje osnovne ovisnosti s Guiceom

3.1. Naš uzorak aplikacije

Radit ćemo sa scenarijem u kojem dizajniramo tečajeve koji podržavaju tri načina komunikacije u poslovima službe za pomoć: e-pošta, SMS i IM.

Razmotrite razred:

komunikacija javne klase {@Inject private logger logger; @Inject private Communicator komunikator; javna komunikacija (logička KeepRecords) {if (keepRecords) {System.out.println ("Omogućeno zapisivanje poruka"); }} javna logička adresa sendMessage (niz poruka) {return communicator.sendMessage (poruka); }}

Ovaj Komunikacija razred je osnovna jedinica komunikacije. Primjer ove klase koristi se za slanje poruka putem dostupnih komunikacijskih kanala. Kao što je prikazano gore, Komunikacija ima Komunikator koje koristimo za stvarni prijenos poruke.

Osnovna ulazna točka u Guice je Injektor:

javna statička void glavna (String [] args) {Injector injector = Guice.createInjector (novi BasicModule ()); Komunikacija comms = injector.getInstance (Communication.class); } 

Ova glavna metoda dohvaća primjerak našeg Komunikacija razred. Također uvodi temeljni koncept Guicea: Modul (koristeći BasicModule u ovom primjeru). The Modul je osnovna jedinica definicije veza (ili ožičenje, kao što je poznato u proljeće).

Guice je usvojio prvi pristup kod uvođenja ovisnosti i upravljanja tako da nećete imati posla s puno XML-a izravno.

U gornjem primjeru, stablo ovisnosti od Komunikacija implicitno će se ubrizgati pomoću značajke tzv pravovremeno vezivanje, pod uvjetom da klase imaju zadani no-arg konstruktor. Ovo je značajka u Guiceu od početka, a dostupno je tek u proljeće od v4.3.

3.2. Guice vezovi

Vezivanje je na Guice kao i ožičenje na Spring. S vezima, ti definirati kako će Guice ubrizgati ovisnosti u razred.

Obveznica je definirana u provedbi com.google.inject.AbstractModule:

javna klasa BasicModule proširuje AbstractModule {@Override protected void configure () {bind (Communicator.class) .to (DefaultCommunicatorImpl.class); }}

Ova implementacija modula navodi da instanca ZadanoCommunicatorImpl treba ubrizgati gdje god a Komunikator pronađena je varijabla.

Druga inkarnacija ovog mehanizma je imenovan obvezujući. Razmotrite sljedeću deklaraciju varijable:

@Inject @Named ("DefaultCommunicator") komunikator komunikatora; 

Za to ćemo imati sljedeću obvezujuću definiciju:

@Override protected void configure () {bind (Communicator.class) .annotatedWith (Names.named ("DefaultCommunicator")) .to (Communicator.class); } 

Ovo će vezivanje pružiti primjerak Komunikator na varijablu označenu s @Named ("DefaultCommunicator") bilješka.

Primijetit ćete @Ubrizgati i @Name čini se da su napomene napomene o zajmu iz CDI-ja Jakarte EE, i jesu. Oni su u com.google.inject. * paket - trebali biste biti oprezni pri uvozu iz pravog paketa kada koristite IDE.

Savjet: Iako smo upravo rekli da se koristimo Guiceom @Ubrizgati i @Name, vrijedi napomenuti da Guice pruža podršku za javax.injekt.Injekt i javax.inject.Named, među ostalim bilješkama EE Jakarte.

Također možete ubrizgati ovisnost koja nema zadani no-arg konstruktor koji koristi vezivanje konstruktora:

javna klasa BasicModule proširuje AbstractModule {@Override protected void configure () {bind (Boolean.class) .toInstance (true); bind (Communication.class) .toConstructor (Communication.class.getConstructor (Boolean.TYPE)); } 

Gornji isječak ubrizgat će primjerak Komunikacija koristeći konstruktor koji uzima a boolean argument. Mi isporučujemo pravi argument konstruktoru pomoću definiranje an neciljano vezivanje od Booleova razred.

Ovaj neciljano vezivanje bit će željno isporučen bilo kojem konstruktoru u povezu koji prihvaća a boolean parametar. Ovim pristupom, sve ovisnosti od Komunikacija se injektiraju.

Drugi pristup vezivanju specifičnom za konstruktor je primjerak obvezujući, gdje pružamo primjerak izravno u povezu:

javna klasa BasicModule proširuje AbstractModule {@Override protected void configure () {bind (Communication.class) .toInstance (nova komunikacija (istinito)); }}

Ovo će vezivanje pružiti primjerak Komunikacija razred gdje god a Komunikacija deklarirana je varijabla.

U ovom slučaju, međutim, stablo ovisnosti klase neće se automatski ožičiti. Trebali biste ograničiti upotrebu ovog načina rada tamo gdje nije potrebna velika inicijalizacija ili ubrizgavanje ovisnosti.

4. Vrste ubrizgavanja ovisnosti

Guice podržava standardne vrste injekcija koje biste očekivali s DI uzorkom. U Komunikator klase, moramo ubrizgati različite vrste Način komunikacije.

4.1. Ubrizgavanje polja

@Inject @Named ("SMSComms") CommunicationMode smsComms;

Koristite neobavezno @Name napomena kao kvalifikator za provedbu ciljanog ubrizgavanja na temelju imena

4.2. Metoda Injekcija

Ovdje koristimo metodu postavljanja kako bismo postigli ubrizgavanje:

@Inject public void setEmailCommunicator (@Named ("EmailComms") CommunicationMode emailComms) {this.emailComms = emailComms; } 

4.3. Injektiranje konstruktora

Također možete ubrizgati ovisnosti pomoću konstruktora:

@Ubrizgavanje javne komunikacije (@Named ("IMComms") CommunicationMode imComms) {this.imComms = imComms; } 

4.4. Implicitne injekcije

Guice će implicitno ubrizgati neke komponente opće namjene poput Injektor i primjerak java.util.Logger, između ostalih. Primijetit ćete da koristimo biljege kroz sve uzorke, ali za njih nećete pronaći stvarno povezivanje.

5. Scoping u Guiceu

Guice podržava opsege i mehanizme opsega na koje smo navikli u drugim DI okvirima. Guice prema zadanim postavkama pruža novu instancu definirane ovisnosti.

5.1. Singleton

Ubrizgamo jednostruko u našu aplikaciju:

bind (Communicator.class) .annotatedWith (Names.named ("AnotherCommunicator")) .to (Communicator.class) .in (Scopes.SINGLETON); 

The u (Scopes.SINGLETON) određuje da bilo koji Komunikator polje s @Named ("AnotherCommunicator") ubrizgati će jednostruko. Ovaj je singleton lijeno iniciran prema zadanim postavkama.

5.2. Nestrpljivi Singleton

Sada, ubrizgajmo željnog singletona:

bind (Communicator.class) .annotatedWith (Names.named ("AnotherCommunicator")) .to (Communicator.class) .asEagerSingleton (); 

The asEagerSingleton () call definira singletona kao željno instanciran.

Uz ova dva opsega, Guice podržava prilagođene opsege, kao i samo web @RequestScoped i @SessionScoped napomene, isporučuje ih Jakarta EE (ne postoje verzije tih napomena koje je isporučio Guice).

6. Aspektno orijentirano programiranje u Guiceu

Guice je usklađen sa AOPAlliance-ovim specifikacijama za aspektno orijentirano programiranje. Najvažniji presretač bilježenja, koji ćemo koristiti za praćenje slanja poruka u našem primjeru, možemo implementirati u samo četiri koraka.

Korak 1 - Primijenite AOPAlliance MethodInterceptor:

javna klasa MessageLogger implementira MethodInterceptor {@Inject Logger logger; @Override javni objektni poziv (invocation MethodInvocation) baca Throwable {Object [] objectArray = invocation.getArguments (); za (Objekt objekt: objectArray) {logger.info ("Slanje poruke:" + object.toString ()); } vratiti invocation.proceed (); }} 

Korak 2 - Definirajte običnu Java napomenu:

@Retention (RetentionPolicy.RUNTIME) @Target (ElementType.METHOD) public @interface MessageSentLoggable {} 

Korak 3 - Definirajte vezu za podudaranje:

Podudaranje je klasa Guice koju koristimo, a određuju komponente na koje će se primijeniti naša AOP napomena. U ovom slučaju želimo da se napomena odnosi na implementacije Način komunikacije:

javna klasa AOPModule proširuje AbstractModule {@Override protected void configure () {bindInterceptor (Matchers.any (), Matchers.annotatedWith (MessageSentLoggable.class), new MessageLogger ()); }} 

Naveli smo a Podudaranje ovdje će se primijeniti naša MessageLogger presretač do bilo koji razred, koji ima MessageSentLoggable bilješka primijenjena na njegove metode.

Korak 4 - Primijenite našu napomenu na naš komunikacijski način i učitajte naš modul

@Override @MessageSentLoggable javni boolean sendMessage (String poruka) {logger.info ("SMS poruka poslana"); povratak istinit; } public static void main (String [] args) {Injector injector = Guice.createInjector (novi BasicModule (), novi AOPModule ()); Komunikacija comms = injector.getInstance (Communication.class); }

7. Zaključak

Razmotrivši osnovnu Guiceovu funkcionalnost, možemo vidjeti odakle je inspiracija za Guice proljeće.

Zajedno s podrškom za JSR-330, Guice želi biti DI okvir usmjeren na ubrizgavanje (dok Spring pruža čitav ekosustav za praktičnost programiranja, a ne nužno samo DI), usmjeren na programere koji žele DI fleksibilnost.

Guice je također vrlo proširiv, omogućavajući programerima da napišu prijenosne dodatke koji rezultiraju fleksibilnom i kreativnom uporabom okvira. To je dodatak opsežnoj integraciji koju Guice već nudi za najpopularnije okvire i platforme poput Servlets, JSF, JPA i OSGi, da nabrojimo samo neke.

Sve izvorne kodove korištene u ovom vodiču možete pronaći u našem GitHub projektu.