Bevezetés a tavaszba Akkával

1. Bemutatkozás

Ebben a cikkben arra összpontosítunk, hogy integráljuk az Akkát a tavaszi keretrendszerbe - lehetővé téve a tavaszi alapú szolgáltatások injektálását az Akka szereplőihez.

A cikk elolvasása előtt ajánlott az Akka alapjainak előzetes ismerete.

2. Függőségi injekció Akkában

Az Akka az Actor egyidejűségi modellen alapuló hatékony alkalmazási keretrendszer. A keretrendszer Scalában íródott, ami természetesen teljes mértékben használhatóvá teszi a Java-alapú alkalmazásokban is. És aztán nagyon gyakran szeretnénk az Akkát integrálni egy meglévő tavaszi alkalmazásba vagy egyszerűen használja a Spring-et babok bekötésére a színészekre.

A tavaszi / akkai integráció problémája abban rejlik, hogy különbség van a bab tavaszi kezelése és az akkai szereplők irányítása között: a színészeknek van egy meghatározott életciklusuk, amely eltér a tipikus tavaszi bab életciklusától.

Sőt, a szereplőket felosztják magára színészre (ami egy belső megvalósítási részlet, és Spring nem tudja kezelni), és egy színészreferenciára, amely kliens kóddal érhető el, valamint sorosítható és hordozható a különböző Akka futások között.

Szerencsére az Akka biztosít egy olyan mechanizmust, nevezetesen az Akka kiterjesztéseket, amely meglehetősen egyszerű feladattá teszi a külső függőség-befecskendezési keretrendszerek használatát.

3. Maven-függőségek

Az Akka tavaszi projektünkben való használatának bemutatásához szükségünk lesz egy minimális tavaszi függőségre - a tavaszi kontextus könyvtár, valamint a akka-színész könyvtár. A könyvtár verziói kibonthatók a szakasza pom:

 4.3.1.RELEASE 2.4.8 org.springframework spring-context $ {spring.version} com.typesafe.akka akka-színész_2.11 $ {akka.version} 

Győződjön meg róla, hogy a Maven Central webhelyen van-e a legújabb verziója tavaszi kontextus és akka-színész függőségek.

És vedd észre, hogyan, hogy a akka-színész a függőségnek van egy _2.11 postfix a nevében, ami azt jelzi, hogy az Akka keretrendszer ezen verziója a Scala 2.11 verziójával szemben épült. A Scala könyvtár megfelelő verziója átmenetileg beépül az építkezésbe.

4. Tavaszi bab befecskendezése az Akka színészek közé

Hozzunk létre egy egyszerű Spring / Akka alkalmazást, amely egyetlen szereplőből áll, és válaszolhat egy személy nevére azzal, hogy üdvözletet ad ennek a személynek. Az üdvözlés logikáját egy külön szolgáltatásba vonják ki. Szeretnénk automatikusan bekapcsolni ezt a szolgáltatást egy színészpéldányhoz. A tavaszi integráció segít ebben a feladatban.

4.1. Színész és szolgáltatás meghatározása

Létrehozunk egy egyszerű osztályt annak bemutatására, hogy egy színésznek milyen szolgáltatása van a színész számára GreetingActor meghatározhatatlan színész (kiterjesztve az Akka-okat) UntypedActor alaposztály). Minden Akka színész fő módszere a onReceive metódus, amely üzenetet fogad és valamilyen meghatározott logika szerint dolgozza fel.

Esetünkben a GreetingActor a megvalósítás ellenőrzi, hogy az üzenet előre meghatározott típusú-e Üdvözöl, majd átveszi a személy nevét a Üdvözöl példányt, majd a GreetingService hogy üdvözletet kapjon erről a személyről, és válaszoljon a küldőre a kapott üdvözlő karakterlánccal. Ha az üzenet valamilyen más ismeretlen típusú, akkor azt a színész előre definiálja kezeletlenül módszer.

Nézzük meg:

A @Component @Scope (ConfigurableBeanFactory.SCOPE_PROTOTYPE) nyilvános osztály A GreetingActor kiterjeszti az UntypedActor {private GreetingService greetingService; // konstruktor @Orride public void onReceive (Object message) dobja a Throwable {if (Üdvözlet üzenet példánya) {String name = ((Köszönt) üzenet) .getName (); getSender (). tell (greetingService.greet (név), getSelf ()); } else {kezeletlen (üzenet); }} public static class Greet {private String name; // szabványos kivitelezők / szerelők}}

Figyeljük meg, hogy a Üdvözöl az üzenettípust statikus belső osztályként definiálják ebben a szereplőben, ami jó gyakorlatnak számít. Az elfogadott üzenettípusokat a lehető legközelebb kell meghatározni egy szereplőhöz, hogy elkerüljük a zavart abban, hogy az üzenet szereplő mely üzenettípusokat képes feldolgozni.

Figyelje meg a tavaszi kommentárokat is @Összetevő és @Scope - ezek az osztályt tavasszal kezelt babként definiálják a prototípus hatálya.

A hatókör nagyon fontos, mert minden babkérési kérelemnek újonnan létrehozott példányt kell eredményeznie, mivel ez a viselkedés megfelel Akka színészének életciklusának. Ha ezt a babot valamilyen más hatókörrel valósítja meg, akkor valószínűleg az Akkában szereplő szereplők újraindítása tipikusan helytelenül fog működni.

Végül vegye észre, hogy nem kellett kifejezetten @Autowire a GreetingService példány - ez a Spring 4.3 új funkciójának köszönhető Implicit konstruktor injekció.

A GreeterService meglehetősen egyértelmű, vegye figyelembe, hogy a Spring hozzáadásával babként definiáltuk a @Összetevő megjegyzés hozzá (alapértelmezettel szingli hatály):

@ Component public class GreetingService {public String greet (String name) {return "Hello," + name; }}

4.2. Tavaszi támogatás hozzáadása az Akka Extension segítségével

A Spring és az Akka integrálásának legegyszerűbb módja az Akka kiterjesztés.

A kiterjesztés egy színészenként létrehozott egyedi példány. Magából a kiterjesztési osztályból áll, amely megvalósítja a marker interfészt Kiterjesztés, és egy kiterjesztés azonosító osztály, amely általában örökli AbstractExtensionId.

Mivel ez a két osztály szorosan összekapcsolódik, célszerű megvalósítani a Kiterjesztés osztály fészkelt a ExtensionId osztály:

public class SpringExtension extends AbstractExtensionId {public static final SpringExtension SPRING_EXTENSION_PROVIDER = new SpringExtension (); @Orride public SpringExt createExtension (ExtendedActorSystem system) {return new SpringExt (); } public static class SpringExt kiterjesztést hajt végre {private volatile ApplicationContext applicationContext; public void inicializálás (ApplicationContext applicationContext) {this.applicationContext = applicationContext; } nyilvános kellékek kellékei (karakterlánc-szereplőBeanName) {return kellékek létrehozása (SpringActorProducer.class, applicationContext, szereplőBeanName); }}}

ElsőSpringExtension végrehajt egy szinglit createExtension módszer a AbstractExtensionId osztály - amely egy kiterjesztéses példány létrehozását jelenti, a SpringExt tárgy.

A SpringExtension osztálynak is van statikus mezője SPRING_EXTENSION_PROVIDER amely egyetlen példányára hivatkozik. Gyakran van értelme hozzáadni egy magánépítőt, hogy ezt kifejezetten kijelentse SpringExtention állítólag egyszemélyes osztály, de az egyértelműség kedvéért kihagyjuk.

Másodszor, a statikus belső osztály SpringExt maga a kiterjesztés. Mint Kiterjesztés egyszerűen egy marker felület, definiálhatjuk ennek az osztálynak a tartalmát, ahogy jónak látjuk.

Esetünkben szükségünk lesz a inicializálni módszer a tavasz megtartására ApplicationContext példány - ezt a módszert csak egyszer hívják meg kiterjesztés inicializálásakor.

Szükségünk lesz a kellékek módszer a Kellékek tárgy. Kellékek példány egy színész tervrajza, esetünkben pedig Kellékek.hozza létre módszer megkapja a SpringActorProducer osztály és konstruktor érvek ehhez az osztályhoz. Ezekkel az érvekkel hívják meg az osztály konstruktorát.

A kellékek A módszer minden alkalommal végrehajtásra kerül, amikor szükségünk lesz egy Spring által irányított színész referenciára.

A harmadik és a puzzle utolsó darabja az SpringActorProducer osztály. Megvalósítja az Akka's-t IndirectActorProducer interfész, amely lehetővé teszi a szereplők számára a példányosítás folyamatának felülírását a termelni és színészosztály mód.

Mint valószínűleg már sejtette, közvetlen példányosítás helyett mindig egy színészpéldányt fog kinyerni a tavaszból ApplicationContext. Ahogy a színészt a prototípus-magos bab, minden hívás a termelni metódus a szereplő új példányát adja vissza:

public class SpringActorProducer megvalósítja az IndirectActorProducer {private ApplicationContext applicationContext; privát String beanActorName; public SpringActorProducer (ApplicationContext applicationContext, String beanActorName) {this.applicationContext = applicationContext; this.beanActorName = beanActorName; } @Orride public Actor produc () {return (Actor) applicationContext.getBean (beanActorName); } @Orride public class actorClass () {return (osztály) applicationContext .getType (beanActorName); }}

4.3. Összedobva az egészet

Csak annyit kell tennie, hogy létrehozzon egy Spring konfigurációs osztályt @ Konfiguráció megjegyzés), amely megmondja Springnek, hogy vizsgálja meg az aktuális csomagot az összes beágyazott csomaggal együtt (ezt a @ComponentScan kommentár) és hozzon létre egy Spring tárolót.

Csak egyetlen további babot kell hozzáadnunk - a ActorSystem példány - és erre inicializálja a Spring kiterjesztést ActorSystem:

@Configuration @ComponentScan public class AppConfiguration {@Autowired private ApplicationContext applicationContext; @Bean public ActorSystem activSystem () {ActorSystem system = ActorSystem.create ("akka-spring-demo"); SPRING_EXTENSION_PROVIDER.get (rendszer) .initialize (applicationContext); visszatérési rendszer; }}

4.4. Rugós vezetékes színészek visszakeresése

Annak tesztelésére, hogy minden megfelelően működik-e, beadhatjuk a ActorSystem például a kódunkba (vagy néhány Spring által kezelt alkalmazáskód, vagy Spring-alapú teszt) hozzon létre egy Kellékek objektum egy színész számára a kiterjesztésünk használatával, a hivatkozás segítségével szerezzen be egy színészre való hivatkozást Kellékek tiltakozzon, és próbáljon meg köszönni valakinek:

ActorRef greeter = system.actorOf (SPRING_EXTENSION_PROVIDER.get (system) .props ("greetingActor"), "greeter"); FiniteDuration duration = FiniteDuration.create (1, TimeUnit.SECONDS); Timeout timeout = Timeout.durationToTimeout (időtartam); Jövőbeli eredmény = ask (üdvözlő, új Greet ("John"), timeout); Assert.assertEquals ("Hello, John", Várj.eredmény (eredmény, időtartam));

Itt a tipikusat használjuk akka.pattern.Patterns.ask minta, amely egy Scala-t ad vissza Jövő példa. A számítás befejezése után a Jövő egy olyan értékkel oldódik meg, amelyet a sajátunkban adtunk vissza GreetingActor.onMessasge módszer.

Vagy várhatunk az eredményre a Scala alkalmazásával Várjon.eredmény módszer a Jövő, vagy még előnyösebben a teljes alkalmazást aszinkron mintákkal építjük fel.

5. Következtetés

Ebben a cikkben megmutattuk, hogyan lehet integrálni a Spring Framework-t az Akkával és az autowire babkal a szereplőkbe.

A cikk forráskódja elérhető a GitHubon.