Uvod u proljeće s Akkom

1. Uvod

U ovom ćemo se članku usredotočiti na integriranje Akke s Spring Frameworkom - kako bismo omogućili ubrizgavanje usluga temeljenih na Spring na akcijske aktere.

Prije čitanja ovog članka preporučuje se prethodno poznavanje Akkinih osnova.

2. Injekcija ovisnosti u Akki

Akka je moćan aplikacijski okvir zasnovan na modelu istodobnosti glumca. Okvir je napisan u Scali što ga, naravno, čini u potpunosti upotrebljivim i u aplikacijama temeljenim na Javi. I tako vrlo često ćemo htjeti integrirati Akku s postojećom aplikacijom temeljenom na Springu ili jednostavno upotrijebite Proljeće za spajanje graha u glumce.

Problem integracije Spring / Akka leži u razlici između upravljanja grahom u proljeće i upravljanja akterima u Akki: glumci imaju specifičan životni ciklus koji se razlikuje od tipičnog životnog ciklusa proljetnog graha.

Štoviše, glumci su podijeljeni na samog glumca (koji je interni detalj implementacije i kojim Spring ne može upravljati) i referencu glumca, kojoj je dostupan klijentski kôd, kao i serializirajuću i prenosivu između različitih Akka vremena izvođenja.

Srećom, Akka nudi mehanizam, odnosno Akka proširenja, koji upotrebu okvira za ubrizgavanje vanjske ovisnosti čini prilično laganim zadatkom.

3. Ovisnosti Mavena

Da bismo demonstrirali uporabu Akke u našem projektu Spring, trebat će nam minimalna ovisnost o Springu - proljeće-kontekst knjižnica, a također i akka-glumac knjižnica. Verzije knjižnice mogu se izdvojiti u odjeljak pom:

 4.3.1.IZBUĐENJE 2.4.8 org.springframework spring-context $ {spring.version} com.typesafe.akka akka -ctor_2.11 $ {akka.version} 

Obavezno provjerite Maven Central za najnovije verzije sustava Windows proljeće-kontekst i akka-glumac ovisnosti.

I primijetite kako, taj akka-glumac ovisnost ima a _2.11 postfix u svom imenu, što znači da je ova verzija Akka framework-a izgrađena u odnosu na verziju Scala 2.11. Odgovarajuća verzija Scala knjižnice bit će tranzitivno uključena u vašu izgradnju.

4. Ubrizgavanje proljetnog graha u glumce Akka

Stvorimo jednostavnu aplikaciju Spring / Akka koja se sastoji od jednog glumca koji može odgovoriti na ime osobe uputivši joj pozdrav. Logika pozdravljanja izdvojit će se u zasebnu uslugu. Morat ćemo ovu uslugu automatski povezati s glumcem. Proljetna integracija pomoći će nam u ovom zadatku.

4.1. Definiranje glumca i usluge

Da bismo demonstrirali ubrizgavanje usluge u glumca, stvorit ćemo jednostavnu klasu Pozdravni glumac definiran kao netipizirani glumac (produžujući Akka's UntypedActor osnovna klasa). Glavna metoda svakog glumca iz Akke je onReceive metoda koja prima poruku i obrađuje je prema određenoj logici.

U našem slučaju, Pozdravni glumac implementacija provjerava je li poruka unaprijed definiranog tipa Pozdraviti, zatim uzima ime osobe iz Pozdraviti instanci, zatim koristi Pozdravna usluga da primi čestitku za ovu osobu i odgovori pošiljatelju primljenim nizom pozdrava. Ako je poruka neke druge nepoznate vrste, ona se prosljeđuje unaprijed definiranom glumcu neobrađen metoda.

Pogledajmo:

@Component @Scope (ConfigurableBeanFactory.SCOPE_PROTOTYPE) javna klasa GreetingActor proširuje UntypedActor {private GreetingService pozdravService; // konstruktor @Override public void onReceive (Object message) baca Throwable {if (message instanceof Greet) {String name = ((Greet) message) .getName (); getSender (). tell (pozdravService.greet (ime), getSelf ()); } else {neobrađeno (poruka); }} javna statička klasa Pozdravi {naziv privatnog niza; // standardni konstruktori / getteri}}

Primijetite da Pozdraviti vrsta poruke definira se kao statička unutarnja klasa unutar ovog glumca, što se smatra dobrom praksom. Prihvaćene vrste poruka trebaju biti definirane što bliže glumcu kako bi se izbjegla zabuna oko toga koje vrste poruka taj glumac može obraditi.

Također primijetite proljetne bilješke @Komponenta i @Skop - oni definiraju klasu kao grah kojim upravlja proljeće s prototip opseg.

Opseg je vrlo važan, jer bi svaki zahtjev za pronalaženjem graha trebao rezultirati novostvorenom instancom, jer ovo ponašanje odgovara životnom ciklusu Akkinog glumca. Ako ovaj bean implementirate s nekim drugim opsegom, tipični slučaj ponovnog pokretanja glumaca u Akki vjerojatno će funkcionirati pogrešno.

Napokon, primijetite da nismo morali izričito @Autowire the Pozdravna usluga instanca - to je moguće zbog nove značajke proljeća 4.3 Implicitno ubrizgavanje konstruktora.

Provedba GreeterService je prilično jednostavan, primijetite da smo ga definirali kao grah kojim upravlja proljeće dodavanjem znaka @Komponenta bilješka uz nju (sa zadanim jednokrevetna opseg):

@Component javna klasa GreetingService {javni String pozdrav (naziv niza) {return "Zdravo," + ime; }}

4.2. Dodavanje proljetne podrške putem produžetka Akka

Najjednostavniji način integriranja proljeća s Akkom je kroz proširenje Akka.

Proširenje je pojedinačna instanca stvorena po sustavu glumca. Sastoji se od same klase proširenja koja implementira sučelje markera Proširenjei klasa id ekstenzije koja obično nasljeđuje SažetakEkstenzijaId.

Kako su ove dvije klase usko povezane, logično je implementirati Proširenje klasa ugniježđena unutar ExtensionId razred:

javna klasa SpringExtension proteže se AbstractExtensionId {public static final SpringExtension SPRING_EXTENSION_PROVIDER = new SpringExtension (); @Preuzmi javni SpringExt createExtension (sustav ExtendedActorSystem) {return new SpringExt (); } javna statička klasa SpringExt implementira proširenje {private volatile ApplicationContext applicationContext; javna void inicijalizacija (ApplicationContext applicationContext) {this.applicationContext = applicationContext; } javni rekviziti rekvizita (niz glumačkog imena) {return Props.create (SpringActorProducer.class, applicationContext, actorBeanName); }}}

PrviProljećeEkstenzija provodi jedan createExtention metoda iz SažetakEkstenzijaId klasa - koja predstavlja stvaranje ekstenzije proširenja, SpringExt objekt.

The ProljećeEkstenzija klasa također ima statičko polje SPRING_EXTENSION_PROVIDER koja sadrži referencu na svoj jedini primjer. Često ima smisla dodati privatni konstruktor da se to izričito navede SpringExtention trebao bi biti singleton klasa, ali izostavit ćemo ga radi jasnosti.

Drugo, statička unutarnja klasa SpringExt je samo produženje. Kao Proširenje je jednostavno sučelje markera, sadržaj ove klase možemo definirati kako nam odgovara.

U našem slučaju trebat će nam inicijalizirati metoda držanja izvora ApplicationContext instanca - ova će se metoda pozivati ​​samo jednom po inicijalizaciji proširenja.

Također ćemo zahtijevati rekviziti metoda za stvaranje a Rekviziti objekt. Rekviziti instanca je nacrt za glumca, a u našem slučaju Rekviziti.stvari metoda prima a SpringActorProducer argumenti klase i konstruktora za ovu klasu. To su argumenti s kojima će se pozvati konstruktor ove klase.

The rekviziti metoda izvršit će se svaki put kad nam zatreba referenca glumca kojim upravlja Spring.

Treći a posljednji dio slagalice je SpringActorProducer razred. Provodi Akka's IndirectActorProducer sučelje koje omogućuje nadjačavanje postupka instancije za glumca implementacijom proizvesti i glumacKlasa metode.

Kao što ste vjerojatno već pretpostavili, umjesto izravne instancije, uvijek će dohvatiti glumačku instancu iz Spring-a ApplicationContext. Kao što smo od glumca napravili prototip-skopirani grah, svaki poziv na proizvesti metoda vratit će novu instancu glumca:

javna klasa SpringActorProducer implementira IndirectActorProducer {private ApplicationContext applicationContext; private String beanActorName; javni SpringActorProducer (ApplicationContext applicationContext, String beanActorName) {this.applicationContext = applicationContext; this.beanActorName = beanActorName; } @Override public Actor produce () {return (Actor) applicationContext.getBean (beanActorName); } @Override javna klasa glumacClass () {return (klasa) applicationContext .getType (beanActorName); }}

4.3. Sve to zajedno

Preostalo je samo stvoriti klasu Spring konfiguracije (označenu s @Konfiguracija napomena) koja će Springu reći da skenira trenutni paket zajedno sa svim ugniježđenim paketima (to osigurava @ComponentScan napomena) i stvorite Spring spremnik.

Trebamo dodati samo jedan dodatni grah - ActorSystem instance - i inicijalizirajte proširenje Spring na ovome ActorSystem:

@Configuration @ComponentScan javna klasa AppConfiguration {@Autowired private ApplicationContext applicationContext; @Bean javni ActorSystemctorSystem () {ActorSystem system = ActorSystem.create ("akka-spring-demo"); SPRING_EXTENSION_PROVIDER.get (system) .inicialize (applicationContext); sustav povrata; }}

4.4. Dohvaćanje proljetno ožičenih glumaca

Da bismo provjerili radi li sve ispravno, možemo ubrizgati ActorSystem instancu u naš kôd (ili neki aplikacijski kôd kojim upravlja Spring, ili test temeljen na Springu), stvorite a Rekviziti objekt za glumca pomoću našeg proširenja, dohvatite referencu na glumca putem Rekviziti usprotivite se i pokušajte pozdraviti nekoga:

ActorRef greeter = system.actorOf (SPRING_EXTENSION_PROVIDER.get (system) .props ("pozdravni glumac"), "greeter"); Trajanje konačnog trajanja = FiniteDuration.create (1, TimeUnit.SECONDS); Timeout timeout = Timeout.durationToTimeout (trajanje); Budući rezultat = pitaj (pozdrav, novi Greet ("John"), timeout); Assert.assertEquals ("Zdravo, John", Await.result (rezultat, trajanje));

Ovdje se koristimo tipičnim akka. Pattern.Patterns.ask uzorak koji vraća Scala-inu Budućnost primjer. Nakon završetka izračuna, Budućnost rješava se vrijednošću koju smo vratili u našem GreetingActor.onMessasge metoda.

Možda ćemo pričekati rezultat primjenom Scala-e Čekajte.rezultat metoda za Budućnostili, još poželjnije, izraditi cjelokupnu aplikaciju s asinkronnim uzorcima.

5. Zaključak

U ovom smo članku pokazali kako integrirati Spring Framework s Akkom i autowire grahom u glumce.

Izvorni kôd članka dostupan je na GitHubu.