Veiledning til Google Guice

1. Introduksjon

Denne artikkelen vil undersøkes det grunnleggende i Google Guice. Vi ser på tilnærminger for å fullføre grunnleggende oppgaver for avhengighetsinjeksjon (DI) i Guice.

Vi vil også sammenligne og kontrast Guice-tilnærmingen til de mer etablerte DI-rammene som Spring and Contexts and Dependency Injection (CDI).

Denne artikkelen forutsetter at leseren har forståelse for det grunnleggende i avhengighetsinjeksjonsmønsteret.

2. Oppsett

For å bruke Google Guice i Maven-prosjektet ditt, må du legge til følgende avhengighet til din pom.xml:

 com.google.inject guice 4.1.0 

Det er også en samling av Guice-utvidelser (vi vil dekke dem litt senere) her, samt tredjepartsmoduler for å utvide funksjonene til Guice (hovedsakelig ved å gi integrasjon til mer etablerte Java-rammer).

3. Grunnleggende avhengighetsinjeksjon med guice

3.1. Vår prøve søknad

Vi vil jobbe med et scenario der vi designer klasser som støtter tre kommunikasjonsmåter i en helpdesk-virksomhet: E-post, SMS og IM.

Tenk på klassen:

offentlig klassekommunikasjon {@Inject private Logger logger; @Inject private Communicator communicator; offentlig kommunikasjon (boolsk keepRecords) {if (keepRecords) {System.out.println ("Meldingslogging aktivert"); }} offentlig boolsk sendMessage (strengmelding) {return communicator.sendMessage (melding); }}

Dette Kommunikasjon klasse er den grunnleggende kommunikasjonsenheten. En forekomst av denne klassen brukes til å sende meldinger via tilgjengelige kommunikasjonskanaler. Som vist ovenfor, Kommunikasjon har en Kommunikator som vi bruker for å utføre den faktiske meldingsoverføringen.

Det grunnleggende inngangspunktet til Guice er Injektor:

public static void main (String [] args) {Injector injector = Guice.createInjector (new BasicModule ()); Kommunikasjonskommuner = injektor.getInstance (Kommunikasjon.klasse); } 

Denne hovedmetoden henter en forekomst av vår Kommunikasjon klasse. Det introduserer også et grunnleggende konsept med Guice: the Modul (ved hjelp av BasicModule i dette eksemplet). De Modul er den grunnleggende definisjonen av bindinger (eller ledninger, som det er kjent om våren).

Guice har tatt i bruk en kode-første tilnærming for avhengighetsinjeksjon og -administrasjon slik at du ikke kommer til å håndtere mye XML utenom boksen.

I eksemplet ovenfor er avhengighetstreet til Kommunikasjon vil bli implisitt injisert ved hjelp av en funksjon som heter just-in-time binding, forutsatt at klassene har standard no-arg konstruktør. Dette har vært en funksjon i Guice siden oppstarten og bare tilgjengelig på våren siden v4.3.

3.2. Guice Bindinger

Binding er å Guice som ledninger er til våren. Med bindinger, du definere hvordan Guice skal injisere avhengigheter inn i en klasse.

En binding er definert i en implementering av com.google.inject.AbstractModule:

offentlig klasse BasicModule utvider AbstractModule {@Override-beskyttet ugyldig konfigurere () {bind (Communicator.class) .to (DefaultCommunicatorImpl.class); }}

Denne modulimplementeringen spesifiserer at en forekomst av MisligholdeCommunicatorImpl skal injiseres hvor som helst a Kommunikator variabel er funnet.

En annen inkarnasjon av denne mekanismen er kalt binding. Vurder følgende variabelerklæring:

@Inject @Named ("DefaultCommunicator") Communicator communicator; 

For dette vil vi ha følgende bindende definisjon:

@ Override beskyttet ugyldig konfigurere () {bind (Communicator.class) .annotatedWith (Names.named ("DefaultCommunicator")) .to (Communicator.class); } 

Denne bindingen vil gi en forekomst av Kommunikator til en variabel som er merket med @Named (“Standardkommunikator”) kommentar.

Du vil legge merke til @Injiser og @Named merknader ser ut til å være lånekommentarer fra Jakarta EEs CDI, og det er de. De er i com.google.inject. * pakke - du bør være forsiktig med å importere fra riktig pakke når du bruker en IDE.

Tips: Mens vi nettopp sa å bruke Guice-gitt @Injiser og @Named, er det verdt å merke seg at Guice gir støtte for javax.inject.Inject og javax.inject.Named, blant andre Jakarta EE-merknader.

Du kan også injisere en avhengighet som ikke har en standard no-arg-konstruktør som bruker konstruktørbinding:

offentlig klasse BasicModule utvider AbstractModule {@Override-beskyttet ugyldig konfigurere () {bind (Boolean.class) .toInstance (true); bind (Communication.class) .toConstructor (Communication.class.getConstructor (Boolean.TYPE)); } 

Utdraget ovenfor vil injisere en forekomst av Kommunikasjon ved hjelp av konstruktøren som tar en boolsk argument. Vi leverer ekte argument til konstruktøren av definere en ikke-målrettet binding av Boolsk klasse.

Dette ikke-målrettet binding vil ivrig bli levert til enhver konstruktør i bindingen som godtar a boolsk parameter. Med denne tilnærmingen, alle avhengigheter av Kommunikasjon blir injisert.

En annen tilnærming til konstruktorspesifikk binding er forekomst bindende, der vi gir en forekomst direkte i bindingen:

offentlig klasse BasicModule utvider AbstractModule {@Override-beskyttet ugyldig konfigurere () {bind (Communication.class) .toInstance (ny kommunikasjon (sann)); }}

Denne bindingen vil gi en forekomst av Kommunikasjon klasse uansett hvor Kommunikasjon variabel er erklært.

I dette tilfellet blir imidlertid ikke avhengighetstreet til klassen automatisk koblet til. Du bør begrense bruken av denne modusen der det ikke er noen tung initialisering eller avhengighetsinjeksjon nødvendig.

4. Typer avhengighetsinjeksjon

Guice støtter de vanlige injeksjonstypene du ville forvente med DI-mønsteret. I Kommunikator klasse, må vi injisere forskjellige typer CommunicationMode.

4.1. Feltinjeksjon

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

Bruk valgfritt @Named kommentar som kvalifiserende for å implementere målrettet injeksjon basert på navnet

4.2. Metode Injeksjon

Her bruker vi en settermetode for å oppnå injeksjonen:

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

4.3. Constructor Injection

Du kan også injisere avhengigheter ved hjelp av en konstruktør:

@Injiser offentlig kommunikasjon (@Named ("IMComms") CommunicationMode imComms) {this.imComms = imComms; } 

4.4. Implisitte injeksjoner

Guice vil implisitt injisere noen generelle komponenter som Injektor og en forekomst av java.util.Logger, blant andre. Du vil merke at vi bruker loggere gjennom prøvene, men du vil ikke finne en faktisk binding for dem.

5. Scoping in Guice

Guice støtter omfanget og avgrensningsmekanismene vi har blitt vant til i andre DI-rammer. Guice er som standard å gi en ny forekomst av en definert avhengighet.

5.1. Singleton

La oss injisere en singleton i applikasjonen vår:

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

De i (Scopes.SINGLETON) angir at noen Kommunikator felt med @Named (“AnotherCommunicator”) vil få en singleton injisert. Denne singleton er lat startet som standard.

5.2. Ivrig Singleton

La oss nå injisere en ivrig singleton:

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

De asEagerSingleton () kall definerer singleton som ivrig instantiert.

I tillegg til disse to omfangene, støtter Guice tilpassede omfang så vel som nettet @RequestScoped og @SessionScoped merknader, levert av Jakarta EE (det er ingen versjoner av disse merknadene som er gitt av Guice).

6. Aspect Oriented Programming in Guice

Guice er i samsvar med AOPAllians spesifikasjoner for aspektorientert programmering. Vi kan implementere den avgjørende loggfangeren, som vi vil bruke til å spore meldingssending i vårt eksempel, i bare fire trinn.

Trinn 1 - Implementer AOPAlliance Metode Interceptor:

offentlig klasse MessageLogger implementerer MethodInterceptor {@Inject Logger logger; @ Override public Object invoke (MethodInvocation invocation) kaster Throwable {Object [] objectArray = invocation.getArguments (); for (Object object: objectArray) {logger.info ("Sender melding:" + object.toString ()); } returner påkallelse. fortsett (); }} 

Trinn 2 - Definer en vanlig Java-kommentar:

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

Trinn 3 - Definer en binding for en matcher:

Matcher er en veiledningsklasse som vi bruker, spesifiserer komponentene som AOP-merknaden vil gjelde for. I dette tilfellet vil vi at merknaden skal gjelde for implementeringer av CommunicationMode:

offentlig klasse AOPModule utvider AbstractModule {@Override-beskyttet ugyldig konfigurere () {bindInterceptor (Matchers.any (), Matchers.annotatedWith (MessageSentLoggable.class), ny MessageLogger ()); }} 

Vi har spesifisert en Matcher her som vil gjelde vår MessageLogger avlytter til noen klasse, som har MessageSentLoggable merknader brukt på metodene.

Trinn 4 - Bruk merknaden vår på kommunikasjonsmodus og last inn modulen vår

@Override @MessageSentLoggable offentlig boolsk sendMessage (strengmelding) {logger.info ("SMS-melding sendt"); returner sant; } public static void main (String [] args) {Injector injector = Guice.createInjector (new BasicModule (), new AOPModule ()); Kommunikasjonskommuner = injektor.getInstance (Kommunikasjon.klasse); }

7. Konklusjon

Etter å ha sett på grunnleggende Guice-funksjonalitet, kan vi se hvor inspirasjonen til Guice kom fra våren.

Sammen med støtten til JSR-330, tar Guice sikte på å være et injeksjonsfokusert DI-rammeverk (mens Spring gir et helt økosystem for programmeringskomfort, ikke nødvendigvis bare DI), rettet mot utviklere som ønsker DI-fleksibilitet.

Guice er også svært utvidbart, slik at programmerere kan skrive bærbare plugins som resulterer i fleksibel og kreativ bruk av rammeverket. Dette er i tillegg til den omfattende integrasjonen som Guice allerede tilbyr for de mest populære rammene og plattformene som Servlets, JSF, JPA og OSGi, for å nevne noen.

Du finner all kildekoden som brukes i denne opplæringen i GitHub-prosjektet vårt.


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