Introduktion til foråret med Akka

1. Introduktion

I denne artikel vil vi fokusere på at integrere Akka med Spring Framework - for at tillade indsprøjtning af Spring-baserede tjenester i Akka-aktører.

Inden du læser denne artikel, anbefales det at have forudgående kendskab til Akkas grundlæggende.

2. Afhængighedsinjektion i Akka

Akka er en stærk applikationsramme baseret på Actor concurrency-modellen. Rammen er skrevet i Scala, hvilket naturligvis også gør den fuldt anvendelig i Java-baserede applikationer. Også det er meget ofte, vi vil integrere Akka med en eksisterende Spring-baseret applikation eller brug foråret til at forbinde bønner til skuespillere.

Problemet med Spring / Akka-integration ligger i forskellen mellem ledelsen af ​​bønner i Spring og ledelsen af ​​aktører i Akka: skuespillere har en bestemt livscyklus, der adskiller sig fra den typiske Spring Bean-livscyklus.

Desuden er skuespillere opdelt i en skuespiller i sig selv (som er en intern implementeringsdetalje og ikke kan styres af Spring) og en skuespillerhenvisning, som er tilgængelig med en klientkode, samt seriel og bærbar mellem forskellige Akka-driftstider.

Heldigvis giver Akka en mekanisme, nemlig Akka-udvidelser, der gør brugen af ​​eksterne afhængighedsinjektionsrammer til en ret let opgave.

3. Maven-afhængigheder

For at demonstrere brugen af ​​Akka i vores forårsprojekt har vi brug for et absolut minimumsafhængighed af foråret - den forårskontekst bibliotek, og også akka-skuespiller bibliotek. Biblioteksversionerne kan udvindes til sektion af pom:

 4.3.1.RELEASE 2.4.8 org.springframework spring-context $ {spring.version} com.typesafe.akka akka-actor_2.11 $ {akka.version} 

Sørg for at tjekke Maven Central for de nyeste versioner af forårskontekst og akka-skuespiller afhængigheder.

Og bemærk hvordan, at den akka-skuespiller afhængighed har en _2.11 postfix i dets navn, hvilket betyder, at denne version af Akka framework blev bygget mod Scala version 2.11. Den tilsvarende version af Scala-biblioteket vil blive inkluderet transitivt i din build.

4. Injektion af forårsbønner i Akka Actors

Lad os oprette en simpel Spring / Akka-applikation bestående af en enkelt aktør, der kan svare på en persons navn ved at udstede en hilsen til denne person. Hilsenens logik udvindes til en separat tjeneste. Vi ønsker at autoled denne tjeneste til en aktørinstans. Forår integration vil hjælpe os i denne opgave.

4.1. Definition af en skuespiller og en tjeneste

For at demonstrere indsprøjtning af en tjeneste i en skuespiller opretter vi en simpel klasse Hilsen skuespiller defineret som en utypet skuespiller (udvidelse af Akkas UntypedActor basisklasse). Den vigtigste metode for enhver Akka-skuespiller er onModtag metode, der modtager en besked og behandler den i henhold til en bestemt logik.

I vores tilfælde er Hilsen skuespiller implementering kontrollerer, om meddelelsen er af en foruddefineret type Hilse, tager derefter navnet på personen fra Hilse eksempel bruger derefter HilsenService for at modtage en hilsen til denne person og svarer afsenderen med den modtagne hilsenstreng. Hvis beskeden er af en anden ukendt type, sendes den til skuespillerens foruddefinerede uhåndteret metode.

Lad os kigge på det:

@Component @Scope (ConfigurableBeanFactory.SCOPE_PROTOTYPE) offentlig klasse GreetingActor udvider UntypedActor {private GreetingService greetingService; // constructor @ Override public void onReceive (Object message) kaster Throwable {if (message instanceof Greet) {String name = ((Greet) message) .getName (); getSender (). tell (greetingService.greet (navn), getSelf ()); } andet {ubehandlet (besked); }} offentlig statisk klasse Hilsen {privat strengnavn; // standard konstruktører / getters}}

Bemærk, at Hilse meddelelsestype defineres som en statisk indre klasse inde i denne aktør, hvilket betragtes som en god praksis. Accepterede meddelelsestyper skal defineres så tæt på en aktør som muligt for at undgå forvirring om, hvilke meddelelsestyper denne aktør kan behandle.

Bemærk også forårets kommentarer @Komponent og @Scope - disse definerer klassen som en fjederstyret bønne med prototype rækkevidde.

Omfanget er meget vigtigt, fordi hver anmodning om bønneudtagning skal resultere i en nyoprettet instans, da denne adfærd matcher Akkas skuespillerlivscyklus. Hvis du implementerer denne bønne med et andet omfang, fungerer det typiske tilfælde af genstart af aktører i Akka sandsynligvis forkert.

Endelig skal du bemærke, at vi ikke behøvede det eksplicit @Autowire det HilsenService eksempel - dette er muligt på grund af den nye funktion i Spring 4.3 kaldet Implicit Constructor Injection.

Gennemførelsen af GreeterService er ret ligetil, bemærk at vi definerede det som en fjederstyret bønne ved at tilføje @Komponent kommentar til det (med standard singleton anvendelsesområde):

@Komponent offentlig klasse GreetingService {public String greet (String name) {return "Hello", + name; }}

4.2. Tilføjelse af forårssupport via Akka Extension

Den nemmeste måde at integrere foråret med Akka på er gennem en Akka-udvidelse.

En udvidelse er en enkelt instans oprettet pr. Aktørsystem. Den består af en udvidelsesklasse, som implementerer markørgrænsefladen Udvidelse, og en udvidelses-id-klasse, der normalt arver AbstractExtensionId.

Da disse to klasser er tæt forbundet, er det fornuftigt at implementere Udvidelse klasse indlejret i ExtensionId klasse:

offentlig klasse SpringExtension udvider AbstractExtensionId {offentlig statisk endelig SpringExtension SPRING_EXTENSION_PROVIDER = ny SpringExtension (); @ Override public SpringExt createExtension (ExtendedActorSystem system) {returner ny SpringExt (); } offentlig statisk klasse SpringExt implementerer udvidelse {privat flygtig ApplicationContext applicationContext; offentlig tomrum initialiseret (ApplicationContext applicationContext) {this.applicationContext = applicationContext; } offentlige rekvisitter (String actorBeanName) {returner Props.create (SpringActorProducer.class, applicationContext, actorBeanName); }}}

FørstSpringExtension implementerer en enkelt createExtension metode fra AbstractExtensionId klasse - der tegner sig for oprettelse af en udvidelsesforekomst, SpringExt objekt.

Det SpringExtension klasse har også et statisk felt SPRING_EXTENSION_PROVIDER som har en henvisning til sin eneste forekomst. Det giver ofte mening at tilføje en privat konstruktør, der udtrykkeligt angiver det SpringExtention formodes at være en singleton-klasse, men vi udelader det for klarhedens skyld.

For det andet, den statiske indre klasse SpringExt er selve udvidelsen. Som Udvidelse er simpelthen en markørgrænseflade, kan vi definere indholdet af denne klasse, som vi finder det passende.

I vores tilfælde har vi brug for initialisere metode til at holde en fjeder ApplicationContext forekomst - denne metode kaldes kun en gang pr. udvidelses initialisering.

Vi vil også kræve rekvisitter metode til oprettelse af en Rekvisitter objekt. Rekvisitter eksempel er en plan for en skuespiller, og i vores tilfælde den Rekvisitter. Opret metoden modtager en SpringActorProducer klasse- og konstruktørargumenter for denne klasse. Dette er argumenterne, som denne klasses konstruktør kaldes til.

Det rekvisitter metoden udføres hver gang vi har brug for en Spring-managed skuespillerhenvisning.

Den tredje og sidste brik i puslespillet er SpringActorProducer klasse. Det implementerer Akkas IndirectActorProducer interface, der gør det muligt at tilsidesætte instantieringsprocessen for en aktør ved at implementere fremstille og skuespillerKlasse metoder.

Som du sikkert allerede har gættet, i stedet for direkte instantiering vil det altid hente en skuespillerinstans fra Spring's ApplicationContext. Som vi har gjort skuespilleren til en prototype- afskåret bønne, hvert opkald til fremstille metoden returnerer en ny instans af skuespilleren:

offentlig klasse SpringActorProducer implementerer IndirectActorProducer {privat ApplicationContext applicationContext; private String beanActorName; public SpringActorProducer (ApplicationContext applicationContext, String beanActorName) {this.applicationContext = applicationContext; this.beanActorName = beanActorName; } @Override public Actor produce () {return (Actor) applicationContext.getBean (beanActorName); } @ Override public Class actorClass () {return (Class) applicationContext .getType (beanActorName); }}

4.3. Samler det hele

Det eneste der er tilbage at gøre er at oprette en Spring-konfigurationsklasse (markeret med @Konfiguration anmærkning), som fortæller Spring at scanne den aktuelle pakke sammen med alle indlejrede pakker (dette sikres af @ComponentScan annotation) og opret en Spring container.

Vi behøver kun at tilføje en ekstra bønne - the ActorSystem eksempel - og initialiser Spring-udvidelsen på dette ActorSystem:

@Configuration @ComponentScan offentlig klasse AppConfiguration {@Autowired privat ApplicationContext applicationContext; @Bean public ActorSystem actorSystem () {ActorSystem system = ActorSystem.create ("akka-spring-demo"); SPRING_EXTENSION_PROVIDER.get (system) .initialize (applicationContext); retur system; }}

4.4. Henter forårskablede skuespillere

For at teste, at alt fungerer korrekt, kan vi injicere ActorSystem forekomst i vores kode (enten en Spring-administreret applikationskode eller en Spring-baseret test), skal du oprette en Rekvisitter objekt til en skuespiller, der bruger vores udvidelse, hente en henvisning til en skuespiller via Rekvisitter modstand og prøv at hilse på nogen:

ActorRef greeter = system.actorOf (SPRING_EXTENSION_PROVIDER.get (system) .props ("greetingActor"), "greeter"); FiniteDuration varighed = FiniteDuration.create (1, TimeUnit.SECONDS); Timeout timeout = Timeout.durationToTimeout (varighed); Fremtidig resultat = spørg (hilsen, ny hilsen ("John"), timeout); Assert.assertEquals ("Hej, John", Await.result (resultat, varighed));

Her bruger vi det typiske akka.pattern.Patterns.ask mønster, der returnerer en Scala's Fremtid eksempel. Når beregningen er afsluttet, Fremtid løses med en værdi, som vi returnerede i vores GreetingActor.onMessasge metode.

Vi kan enten vente på resultatet ved at anvende Scala's Afventer.resultat metode til Fremtideller mere fortrinsvis opbygge hele applikationen med asynkrone mønstre.

5. Konklusion

I denne artikel har vi vist, hvordan man integrerer Spring Framework med Akka og autowire bønner i skuespillere.

Kildekoden til artiklen er tilgængelig på GitHub.


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