Uvod u AspectJ

1. Uvod

Ovaj je članak brz i praktičan uvod u AspectJ.

Prvo ćemo pokazati kako omogućiti aspektno orijentirano programiranje, a zatim ćemo se usredotočiti na razliku između tkanja tijekom prevođenja, naknadnog prevođenja i vremena učitavanja.

Počnimo s kratkim uvođenjem aspektno orijentiranog programiranja (AOP) i osnova AspectJ-a.

2. Pregled

AOP je programska paradigma kojoj je cilj povećati modularnost dopuštajući odvajanje međusobnih problema. To čini dodavanjem dodatnog ponašanja postojećem kodu bez promjene samog koda. Umjesto toga, zasebno izjavljujemo koji ćemo kôd izmijeniti.

AspectJ provodi i brige i tkanje unakrsnih problema koristeći proširenja programskog jezika Java.

3. Ovisnosti Mavena

AspectJ nudi različite knjižnice, ovisno o korištenju. Mavenove ovisnosti možemo pronaći pod grupom org.aspectj u središnjem spremištu Maven.

U ovom se članku usredotočujemo na ovisnosti potrebne za stvaranje aspekata i Weaver koristeći Weavers za vrijeme prevođenja, postkompajliranja i učitavanja.

3.1. AspectJ Runtime

Prilikom izvođenja programa AspectJ, put predavanja trebao bi sadržavati klase i aspekte zajedno s AspectJ runtime knjižnicom aspektjrt.jar:

 org.aspectj aspektrt 1.8.9 

Ova je ovisnost dostupna na Maven Central-u.

3.2. AspectJWeaver

Osim ovisnosti o vremenu izvođenja AspectJ, trebat ćemo uključiti i aspectjweaver.jar za uvođenje savjeta za klasu Java tijekom učitavanja:

 org.aspectj aspektjweaver 1.8.9 

Ovisnost je također dostupna na Maven Central.

4. Stvaranje aspekta

AspectJ pruža provedbu AOP-a i ima ga tri temeljna koncepta:

  • Pridružite se točki
  • Pointcut
  • Savjet

Te ćemo koncepte demonstrirati izradom jednostavnog programa za provjeru stanja korisničkog računa.

Prvo, izradimo Račun klasa s danim saldom i načinom povlačenja:

račun javne klase {int saldo = 20; javno logičko povlačenje (int iznos) {if (saldo <iznos) {return false; } saldo = saldo - iznos; povratak istinit; }}

Stvorit ćemo AccountAspect.aj datoteka za evidentiranje podataka o računu i za provjeru stanja na računu (imajte na umu da datoteke AspectJ završavaju s ".aj”Nastavak datoteke):

javni aspekt AccountAspect {final int MIN_BALANCE = 10; pointcut callWithDraw (int iznos, račun prema): call (boolean Account.withdraw (int)) && args (iznos) && target (acc); prije (int iznos, račun prema): callWithDraw (iznos, prema) {} logički oko (int iznos, račun prema): callWithDraw (iznos, prema) {if (račun po računu <iznos) {return false; } postupak vraćanja (iznos, prema); } nakon (int iznos, stanje na računu): callWithDraw (iznos, stanje) {}}

Kao što vidimo, dodali smo a pointcut na metodu povlačenja i stvorili su tri savjetuje koji se odnose na definirano pointcut.

Da bismo razumjeli sljedeće, uvodimo sljedeće definicije:

  • Aspekt: Modularizacija problema koji presijeca više objekata. Svaki se aspekt usredotočuje na određenu funkcionalnost presijecanja
  • Točka spajanja: Točka tijekom izvođenja skripte, poput izvođenja metode ili pristupa svojstvu
  • Savjet: Radnja koju poduzima aspekt na određenoj točki spajanja
  • Pointcut: Regularni izraz koji odgovara spojnim bodovima. Savjet je povezan s izrazom izrezivanja točke i izvodi se na bilo kojoj točki spajanja koja odgovara izrezivanju točke

Za više detalja o tim konceptima i njihovoj specifičnoj semantici, možda bismo htjeli provjeriti sljedeću poveznicu.

Dalje, moramo utkati aspekte u naš kod. Odjeljci u nastavku odnose se na tri različite vrste tkanja: tkanje tijekom sastavljanja, tkanje nakon sastavljanja i tkanje u vremenu opterećenja u AspectJ.

5. Komplicirano tkanje

Najjednostavniji pristup tkanju je tkanje u vrijeme sastavljanja. Kada imamo i izvorni kod aspekta i kôd u kojem koristimo aspekte, kompajler AspectJ kompajlirat će iz izvora i kao izlaz stvoriti tkane datoteke klase. Nakon toga, po izvršenju vašeg koda, izlazna klasa procesa tkanja učitava se u JVM kao normalna Java klasa.

Možemo preuzeti AspectJ razvojne alate jer uključuje priloženi AspectJ kompajler. Jedna od najvažnijih značajki AJDT-a je alat za vizualizaciju unakrsnih problema, što je korisno za ispravljanje pogrešaka u specifikaciji točke. Možemo vizualizirati kombinirani efekt čak i prije nego što je kôd postavljen.

Koristimo Mojoov dodatak AspectJ Maven da bismo u naše aspekte utkali aspekte AspectJ pomoću kompajlera AspectJ.

 org.codehaus.mojo aspektj-maven-plugin 1,7 1,8 1,8 1,8 istina tačno zanemari UTF-8 kompajliraj test-kompajliraj 

Za više detalja o referencama opcija kompajlera AspectJ, možda ćemo htjeti provjeriti sljedeću poveznicu.

Dodajmo nekoliko testnih slučajeva za našu klasu računa:

javni razred AccountTest {račun privatnog računa; @Prije javne void before () {account = novi račun (); } @Test javna praznina dana20AndMin10_whenWithdraw5_thenSuccess () {assertTrue (account.withdraw (5)); } @Test javna praznina dana20AndMin10_whenWithdraw100_thenFail () {assertFalse (account.withdraw (100)); }}

Kada pokrenemo test slučajeve, donji tekst koji se prikazuje na konzoli znači da smo uspješno tkali izvorni kod:

[INFO] Spoj točke točke 'poziv metode (boolean com.baeldung.aspectj.Account.withdraw (int))' u tipu 'com.baeldung.aspectj.test.AccountTest' (AccountTest.java:20) uz savjet oko 'com.baeldung.aspectj.AccountAspect' (AccountAspect.class: 18 (iz AccountAspect.aj)) [INFO] Metoda poziva točke pridruživanja (logički com.baeldung.aspectj.Account.withdraw (int)) 'u vrsti' com.baeldung.aspectj.test.AccountTest '(AccountTest.java:20) savjetuje se prije savjeta od' com.baeldung.aspectj.AccountAspect '(AccountAspect.class: 13 (iz AccountAspect.aj)) [INFO] Točka pridruživanja' poziv metode (boolean com.baeldung.aspectj.Account.withdraw (int)) 'u vrsti' com.baeldung.aspectj.test.AccountTest '(AccountTest.java:20) savjetuje se nakon savjeta iz' com.baeldung.aspectj .AccountAspect '(AccountAspect.class: 26 (iz AccountAspect.aj)) 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Stanje prije povlačenja: 20. 2016. 11.11. 22: 53:51 [glavna] INFO com.baeldung.aspectj.AccountAspect - Povući iznos: 5. 2016. -11-15 22:53:51 [glavna] INFO com.baeldung.aspectj.AccountAspect - Stanje nakon povlačenja: 15 2016-11-15 22:53:51 [glavna] INFO com.baeldung.aspectj.AccountAspect - Saldo prije povlačenje: 20 2016-11-15 22:53:51 [glavna] INFO com.baeldung.aspectj.AccountAspect - Povući iznos: 100 2016-11-15 22:53:51 [glavna] INFO com.baeldung.aspectj.AccountAspect - Povlačenje odbijeno! 2016-11-15 22:53:51 [glavna] INFO com.baeldung.aspectj.AccountAspect - Stanje nakon povlačenja: 20

6. Tkanje nakon sastavljanja

Tkanje nakon sastavljanja (koje se ponekad naziva i binarno tkanje) koristi se za tkanje postojećih datoteka klase i JAR datoteka. Kao i kod tkanja tijekom sastavljanja, aspekti koji se koriste za tkanje mogu biti u izvornom ili binarnom obliku, a i sami mogu biti utkani po aspektima.

Da bismo to učinili s Mojo-ovim dodatkom AspectJ Maven, potrebno je podesiti sve JAR datoteke koje bismo htjeli utkati u konfiguraciji dodatka:

   org.agroup to-tkati org.anothergroup gen 

JAR datoteke koje sadrže klase za tkanje moraju biti navedene kao u projektu Maven i naveden kao u dodatka AspectJ Maven.

7. Tkanje tijekom opterećenja

Utrošno tkanje jednostavno je odloženo binarno tkanje do trenutka kada učitavač klasa učita datoteku klase i definira klasu u JVM.

Da bi se to podržalo, potreban je jedan ili više utovarivača klase tkanja. Oni se ili izričito pružaju u radnom okruženju ili su omogućeni pomoću „sredstva za tkanje“.

7.1. Omogućavanje tkanja tijekom učitavanja

Tkanje vremena učitavanja AspectJ može se omogućiti pomoću sredstva AspectJ koje se može uključiti u postupak učitavanja klase i tkati bilo koje vrste prije nego što budu definirane u VM-u. Određujemo javaagent opcija za JVM -javaagent: pathto / аспектjweaver.jar ili pomoću dodatka Maven za konfiguriranje javaagent :

 org.apache.maven.plugins maven-surefire-plugin 2.10 -javaagent: "$ {settings.localRepository}" / org / aspektj / aspektweaver / $ {aspekt.verzija} / aspektvejver - $ {aspekt.verzija} .jar true always 

7.2. Konfiguracijski tkač

AspectJ-ovo sredstvo za tkanje tijekom učitavanja konfigurirano je pomoću aop.xml datoteke. Traži jednog ili više njih aop.xml datoteke na stazi u META-INF imenik i objedinjuje sadržaj kako bi odredio konfiguraciju tkalca.

An aop.xml datoteka sadrži dva ključna odjeljka:

  • Aspekti: definira jedan ili više aspekata tkača i kontrolira koji će se aspekti koristiti u procesu tkanja. The aspekti element po želji može sadržavati jedan ili više uključuju i isključiti elementi (prema zadanim postavkama svi definirani aspekti koriste se za tkanje)
  • Tkalac: definira tkalju opcije tkanja i određuje skup tipova koje treba tkati. Ako nisu navedeni elementi za uključivanje, tkati će se sve vrste vidljive tkalcu

Konfigurirajmo aspekt tkalcu:

Kao što vidimo, konfigurirali smo aspekt koji ukazuje na AccountAspect, i samo izvorni kod u com.baeldung.aspectj paket će tkati AspectJ.

8. Bilježenje aspekata

Uz poznati stil deklariranja aspekata zasnovan na kodu AspectJ, AspectJ 5 također podržava stil deklariranja aspekata zasnovan na bilješkama. Skup napomena koji podržavaju ovaj razvojni stil neformalno nazivamo „@AspectJ”Bilješke.

Stvorimo napomenu:

@Retention (RetentionPolicy.RUNTIME) @Target (ElementType.METHOD) public @interface Secured {public boolean isLocked () default false; }

Koristimo @Secured napomena za omogućavanje ili onemogućavanje metode:

javna klasa SecuredMethod {@Secured (isLocked = true) javna praznina lockedMethod () {} @Secured (isLocked = false) javna praznina unlockedMethod () {}}

Dalje, dodajemo aspekt koristeći AspectJ stil napomene i provjeravamo dopuštenje na temelju atributa @Secured napomene:

@Aspect javna klasa SecuredMethodAspect {@Pointcut ("@ annotation (secured)") public void callAt (Secured secured) {} ​​@Around ("callAt (secured)") public Object around (ProceedingJoinPoint pjp, Secured secured) baca bacanje {return osiguran.isLocked ()? null: pjp.proceed (); }}

Za više detalja o stilu napomena AspectJ možemo provjeriti sljedeću poveznicu.

Dalje, tkamo našu klasu i aspekt pomoću tkalca za vrijeme opterećenja i stavljanja aop.xml pod, ispod META-INF mapa:

Na kraju dodajemo jedinični test i provjeravamo rezultat:

@Test public void testMethod () baca iznimku {Usluga SecuredMethod = new SecuredMethod (); service.unlockedMethod (); service.lockedMethod (); }

Kada pokrenemo test slučajeve, možemo provjeriti izlaz konzole kako bismo provjerili jesmo li uspješno utkali svoj aspekt i klasu u izvorni kod:

[INFO] Točka spajanja 'poziv-metoda (void com.baeldung.aspectj.SecuredMethod.unlockedMethod ())' u tipu 'com.baeldung.aspectj.test.SecuredMethodTest' (SecuredMethodTest.java:11) uz savjet oko ' com.baeldung.aspectj.SecuredMethodAspect '(SecuredMethodAspect.class (iz SecuredMethodAspect.java)) 2016-11-15 22:53:51 [glavna] INFO com.baeldung.aspectj.SecuredMethod - otključanaMetoda 15.11.2016 22:53 : 51 [glavna] INFO cbaspectj.SecuredMethodAspect - javna praznina com.baeldung.aspectj.SecuredMethod.lockedMethod () je zaključana

9. Zaključak

U ovom smo članku pokrili uvodne koncepte o AspectJ-u. Za detalje možete pogledati početnu stranicu AspectJ.

Izvorni kod za ovaj članak možete pronaći na GitHubu.