Keresés tartalomra
Kategóriák
Címkék
- Java
- Spring
- Python
- IoC
- Android
- DI
- Dagger
- Thymeleaf
- Markdown
- JDK11
- AOP
- Aspect
- Captcha
- I18n
- JavaSpark
- Microframework
- Testing
- JUnit
- Security
- JWT
- REST
- Database
- JPA
- Gépház
- WebFlux
- ReactiveProgramming
- Microservices
- Continuous Integration
- CircleCI
- Deployment Pipeline
- Docker
- Mocking
- LogProcessing
- PlantUML
- UML
- Modellezés
- OAuth2
- Node.js
- DevOps
- Websocket
AOP alapok Spring keretrendszerben
Építőelemek
Mielőtt belevágnánk, érdemes definiálni néhány alapvető kifejezést, mellyel találkozni fogunk AOP-s funkciók implementálása során. Cikkem bevezető jellege miatt ezúttal csak a legfontosabbak:
Aspect
A legalapvetőbb építőkő az AOP keretrendszerben az aspect. Az aspect az az eszköz, mely “keresztülvágja” az alkalmazás logikáját - ezért is használják az aspect-re a “crosscutting concern” kifejezést. Aspectben írhatjuk le azon funkciókat, melyek az alkalmazás futása során több különböző ponton kell, hogy megjelenjenek - ilyen például a tranzakciókezelés.
Join point
Egy olyan pontja az alkalmazásnak, ahol a tényleges üzleti logikát biztosító kód, és az aspectek találkoznak. Ez jelenthet metódus végrehajtást vagy egy kiváltódó kivételt, bár a Spring AOP keretrendszere csupán előbbit képes kezelni.
Advice
A join point-on végrehajtandó logika. Több fajtája lehet, melyekre még később visszatérek.
Pointcut
A pointcut egy predikátum, mely teljesülése esetén az adott joint point-on végrehajtódik a definiált advice - ez most valószínűleg még magyarázatra szorul, de később példa is lesz rá a cikkben.
Weaving
A weaving során linkeli a keretrendszer az aspect implementációkat az üzleti kódhoz. Történhet futási időben (a Spring AOP ezt a módszert támogatja) vagy fordítási időben is.
Az advice definiálása
Mint azt említettem az advice-oknak több fajtája is létezik, aszerint, hogy mikor futnak, futhatnak le. Ennek megfelelően a következő típusokat különböztetjük meg:
Before
A before típusú advice-ok a join point lefutása előtt hajtódnak végre. Jellegzetessége, hogy hozzáférhetünk többek között a join point-on átadott (metódus) paraméterek tartalmához.
AfterReturning
Az after returning advice-ok a before advice-okkal ellentétben a join point-on visszatérő metódus visszatérési értékéhez adnak hozzáférési lehetőséget.
AfterThrowing
Az after advice-okhoz hasonlóan a join point lefutását követően, de a metódus által kiváltott kivételhez férhetünk hozzá.
After
Az after függetlenül attól, hogy a metódus sikeresen vagy kivétellel tért vissza, mindenképpen lefut.
Around
A legnagyobb rugalmasságot adó advice fajta, mivel - mint a neve is mutatja - a join point köré ékelődik, tehát annak lefutása előtt és után is végrehajthatunk vele extra logikát. Míg az előző advice fajtáknak nem volt szüksége a tényleges join point paraméterként való átadására, az around megköveteli azt. Az advice logikán belül a paraméterként átadott ProceedingJoinPoint példány process() metódusával hajthatjuk végre a wrapelt hívást.
A pointcut definiálása
Bár a Spring AOP csak a metódus alapú join pointok definiálását teszi lehetővé, ahhoz biztosítja minden fontos AOP-s pointcut kifejezés használatát. Sőt, mivel beanekre illesztett join pointokról beszélünk, akár a bean nevére is illeszthetjük azt. Kicsit előre szaladtam, visszatérve a fontosabb kifejezésekre:
Execution
Talán a legalapvetőbb kifejezés, amit a legtöbbször fogunk használni. Az execution pointcut meghatároz egy metódus specifikációt, melyen a join pointunk ül majd. A kifejezésben használhatunk wildcardokat is, így általánosítva a pointcutot, de akár egészen pontosan is kifejezhetjük a kívánt metódus specifikációját (visszatérési típussal, paraméterekkel).
Within
A végrehajtott metódus a megadott típusok egyikében van definiálva. Például megadható egy teljes package is, ekkor a pointcut predikátum bármely olyan metódus végrehajtásakor igaz lesz, mely az adott package-ben található osztályok bármelyikében található.
This
A végrehajtott bean típusára alkalmaz szűrést. Tehát a pointcut igaz lesz, ha a végrehajtás alatt álló metódus egy olyan beanben van definiálva, melynek típusa a this kifejezés paraméterében megadott típus. Ebben és az alább lévő esetekben is az adott típus teljes minősített nevére lesz szükségünk.
Target
A metódus visszatérési típusára alkalmaz szűrést. A pointcut igaz lesz, ha a metódus a target kifejezés paramétereként megadott típusú példánnyal tér vissza.
Args
A metódus argumentumainak típusára alkalmaz szűrést. A pointcut ez esetben akkor lesz igaz, ha a végrehajtott metódusnak van az args kifejezés paramétereként megadott paramétere.
@Target
Az @ szimbólummal kezdődő kifejezések annotációkra, illetve azon jelenlétére szűrnek. Az @target
kifejezés a metódust tartalmazó osztályon levő annotációkra alkalmaz szűrést.
@Args
A metódusnak átadott paraméterek futásidejű típusán lévő annotációkra alkalmaz szűrést.
@Within
Olyan típusokra alkalmaz szűrést, melyek rendelkeznek a paraméterként megadott annotációval.
@Annotation
A pointcut a megadott annotáció jelenlétére figyel majd. Tehát amennyiben a join pointon levő metódus rendelkezik a megadott annotációval, az advice végrehajtásra kerül.
Akkor jöhet a gyakorlat…
Kicsit hosszú lett a bevezető, de nézzük, hogyan fog kinézni egy advice implementáció. Először is, engedélyezni kell az AOP feldolgozást a Spring számára, az @EnableAspectJAutoProxy
annotáció segítségével. Ezt megtehetjük az alkalmazásunk bármelyik @Configuration
annotációval ellátott osztályán, vagy Spring Boot alkalmazás esetén akár a @SpringBootApplication
annotációval ellátott belépési ponton is (röviden a main-t tartalmazó osztályon).
@Configuration
@EnableAspectJAutoProxy
public class ApplicationContextConfig {
// ...
}
Miután ez megvan, készítsünk egy osztályt, melyben az aspect logikáját helyezzük majd el. Persze mindenekelőtt fontos megtervezni, milyen advice-ra lesz szükségünk, mire és milyen logikát szeretnénk ültetni. Az osztálynak mindenesetre szüksége lesz az @Advice
annotációra, ezzel jelezzük ugyanis a framework számára, hogy az osztály egy advice implementációt fog tartalmazni. Fontos megjegyezni, hogy ezzel még nem kerül be a Spring dependency injection kezelése alá, így legalább egy @Component
annotációra még szükségünk lesz - így persze lehetőségünk nyílik arra is, hogy függéseket biztosítsunk az advice számára.
@Aspect
@Component
public class ResponseFillerAspect {
// …
}
A következő lépés a tényleges advice implementálása. A logika belépési pontját tartalmazó metódus neve bármi lehet, a paraméterei és visszatérése ugyanakkor viszonylag kötött. Az advice típusát a megfelelő annotációval tudjuk jelezni, attribútumaként a pointcut kifejezés kötelező, illetve minden típusnak megvannak a saját egyéni attribútumai is. Az alábbiakban két rövid példa látható, természetesen magyarázattal.
@Around(value = "execution(org.springframework.http.ResponseEntity "
+ "hu.psprog.leaflet.web.rest.controller.*.*(..)) "
+ "and @annotation(hu.psprog.leaflet.web.annotation.FillResponse)")
public Object aspectToWrapAnswer(ProceedingJoinPoint proceedingJoinPoint)
// …
Object methodResponse = proceedingJoinPoint.proceed();
// …
return methodResponse;
}
A fenti példa egy @Around
típusú advice, mely a következő join pointra ültet logikát:
- hu.psprog.leaflet.web.rest.controller package-ben található, tetszőleges paraméterekkel rendelkező és ResponseEntity-vel visszatérő metódus végrehajtása
- de csak abban az esetben, ha rendelkezik a FillResponse annotációval.
Mivel az around advice-nak szüksége van a join point-ra, a ProceedingJoinPoint paramétert megkapja a metódus. A tényleges hívás a process() hívással hajtódik végre, addig és azután bármilyen logikával fel lehet tölteni az advice implementációt. Az advice végül visszatér a wrapelt metódus válaszával.
@AfterReturning(
value = "execution(hu.psprog.leaflet.service.vo.EntityPageVO+ "
+ "hu.psprog.leaflet.service.*.*(..))",
returning = "entityPageVO")
void aspectToAutoHandleEntityPageParameters(EntityPageVO<? extends BaseVO> entityPageVO) {
// …
}
Ez pedig egy after returning advice, mely akkor aktiválódik, ha a hu.psprog.leaflet.service package-ben található, tetszőleges paraméterekkel rendelkező metódus kerül végrehajtásra. A kifejezésben még egy érdekesség látható, ez pedig az EntityPageVO+, mely azt jelenti, hogy a metódusnak az EntityPageVO osztályt kiterjesztő osztály példányával kell visszatérnie. Ha a pointcut teljesül, kiemeli az entityPageVO nevű változóba a visszatérési értéket, és átadja az advice implementációnak - ezután az értékkel tetszőleges műveletet hajthatunk végre.
Nos ezzel bevezető jellegű cikkem végére értem. A részletes és teljes dokumentáció elolvasását mindenképpen javaslom az érdeklődőknek, mely az alábbi linken megtalálható:
Részletes dokumentáció az AOP-ről
Komment írásához jelentkezz be
Bejelentkezés
Még senki nem szólt hozzá ehhez a bejegyzéshez.