Úvod do AspectJ

1. Úvod

Tento článok je rýchly a praktický úvod do AspectJ.

Najskôr si ukážeme, ako povoliť aspektovo orientované programovanie, a potom sa zameriame na rozdiel medzi tkaním v čase kompilácie, po kompilácii a načítaním.

Začnime krátkym úvodom do aspektovo orientovaného programovania (AOP) a základov AspectJ.

2. Prehľad

AOP je paradigma programovania, ktorej cieľom je zvýšiť modularitu tým, že umožní oddelenie prierezových problémov. Robí to pridaním dodatočného správania k existujúcemu kódu bez úpravy samotného kódu. Namiesto toho osobitne deklarujeme, ktorý kód sa má upraviť.

AspectJ implementuje obavy aj vytváranie prierezových problémov pomocou rozšírení programovacieho jazyka Java.

3. Závislosti Maven

AspectJ ponúka rôzne knižnice v závislosti od jeho použitia. Závislosti Maven nájdeme pod skupinou org.aspectj v úložisku Maven Central.

V tomto článku sa zameriavame na závislosti potrebné na vytvorenie aspektov a Weaver pomocou tkáčov kompilácie, po kompilácii a načítania.

3.1. AspectJ Runtime

Pri spustení programu AspectJ by cesta triedy mala obsahovať triedy a aspekty spolu s runtime knižnicou AspectJ aspectjrt.jar:

 org.aspectj aspectjrt 1.8.9 

Táto závislosť je k dispozícii na serveri Maven Central.

3.2. AspectJWeaver

Okrem závislosti runtime AspectJ budeme musieť zahrnúť aj aspectjweaver.jar predstaviť rady do triedy Java v čase načítania:

 org.aspectj aspectjweaver 1.8.9 

Závislosť je k dispozícii aj na serveri Maven Central.

4. Vytváranie aspektov

AspectJ poskytuje implementáciu AOP a má tri základné koncepty:

  • Pripojte sa k bodu
  • Pointcut
  • Rada

Tieto koncepty si ukážeme vytvorením jednoduchého programu na overenie zostatku používateľského účtu.

Najprv si vytvorme Účet triedy s daným zostatkom a metódou výberu:

účet verejnej triedy {zostatok = 20; verejny boolean vyber (int suma) {if (zostatok <suma) {return false; } zostatok = zostatok - suma; návrat pravdivý; }}

Vytvoríme AccountAspect.aj do súboru na zaznamenanie informácií o účte a na overenie zostatku na účte (všimnite si, že súbory AspectJ končia znakom „.aj" rozšírenie súboru):

verejný aspekt AccountAspect {final int MIN_BALANCE = 10; pointcut callWithDraw (int suma, Account acc): call (boolean Account.withdraw (int)) && args (amount) && target (acc); before (int amount, Account acc): callWithDraw (amount, acc) {} boolean around (int amount, Account acc): callWithDraw (amount, acc) {if (acc.balance <amount) {return false; } návrat pokračovať (suma, acc); } po (čiastka, zostatok na účte): callWithDraw (čiastka, zostatok) {}}

Ako vidíme, pridali sme a pointcut k metóde výberu a vytvorili tri radí ktoré odkazujú na definované pointcut.

Aby sme pochopili nasledujúce, predstavujeme nasledujúce definície:

  • Aspekt: Modularizácia koncernu, ktorý prechádza cez viaceré objekty. Každý aspekt sa zameriava na konkrétnu prierezovú funkčnosť
  • Pripojte sa k bodu: Bod počas vykonávania skriptu, napríklad vykonanie metódy alebo prístupu k vlastnosti
  • Rada: Činnosť vykonaná aspektom v konkrétnom spojovacom bode
  • Pointcut: Regulárny výraz, ktorý sa zhoduje so spojovacími bodmi. Rada je spojená s výrazom bodového spoja a je spustená v ktoromkoľvek spojovacom bode, ktorý sa zhoduje s bodovým spojom

Ak sa chcete dozvedieť viac podrobností o týchto konceptoch a ich konkrétnej sémantike, pozrite si nasledujúci odkaz.

Ďalej musíme zapracovať aspekty do nášho kódu. Nasledujúce časti sa zaoberajú tromi rôznymi typmi tkania: tkanie v čase kompilácie, tkanie po kompilácii a tkanie v režime načítania v AspectJ.

5. Tkanie v čase kompilácie

Najjednoduchší prístup tkania je tkanie v kompilačnom čase. Keď máme zdrojový kód aspektu aj kód, v ktorom aspekty používame, kompilátor AspectJ bude kompilovať zo zdroja a ako výstup vytvorí súbory triedy woven. Potom, po vykonaní vášho kódu, sa výstupná trieda procesu tkania načíta do JVM ako normálna trieda Java.

Môžeme si stiahnuť vývojové nástroje AspectJ, pretože obsahujú pribalený kompilátor AspectJ. Jednou z najdôležitejších funkcií AJDT je ​​nástroj na vizualizáciu problémov s prierezom, ktorý je nápomocný pri ladení špecifikácie pointcutu. Kombinovaný efekt môžeme vizualizovať ešte pred nasadením kódu.

Používame doplnok Mojo AspectJ Maven, aby sme pomocou našich prekladačov vplietli aspekty AspectJ do našich tried pomocou kompilátora AspectJ.

 org.codehaus.mojo aspectj-maven-plugin 1.7 1.8 1.8 1.8 true true ignorovať kompiláciu UTF-8 test-kompiláciu 

Ak sa chcete dozvedieť viac podrobností o možnostiach kompilátora AspectJ, môžete si pozrieť nasledujúci odkaz.

Pridajme niekoľko testovacích prípadov pre našu triedu účtov:

public class AccountTest {súkromný účet účtu; @Before public void before () {account = new Account (); } @Test public void given20AndMin10_whenWithdraw5_thenSuccess () {assertTrue (account.withdraw (5)); } @Test public void given20AndMin10_whenWithdraw100_thenFail () {assertFalse (account.withdraw (100)); }}

Keď spustíme testovacie prípady, text uvedený nižšie v konzole znamená, že sme úspešne vytvorili zdrojový kód:

[INFO] Pripojte bod „method-call (boolean com.baeldung.aspectj.Account.withdraw (int))“ do typu „com.baeldung.aspectj.test.AccountTest“ (AccountTest.java:20) odporúčaný radou od 'com.baeldung.aspectj.AccountAspect' (AccountAspect.class: 18 (from AccountAspect.aj)) [INFO] Pripojte sa k bodu 'method-call (boolean com.baeldung.aspectj.Account.withdraw (int))' v type ' com.baeldung.aspectj.test.AccountTest '(AccountTest.java:20) odporúčané pred radou od' com.baeldung.aspectj.AccountAspect '(AccountAspect.class: 13 (od AccountAspect.aj)) [INFO] Pripojiť sa k bodu' method-call (boolean com.baeldung.aspectj.Account.withdraw (int)) 'v type' com.baeldung.aspectj.test.AccountTest '(AccountTest.java:20) odporúčané po odporúčaní od' com.baeldung.aspectj .AccountAspect '(AccountAspect.class: 26 (from AccountAspect.aj)) 2016-11-15 22:53:51 [hlavné] INFO com.baeldung.aspectj.AccountAspect - Zostatok pred výberom: 20 2016-11-15 22: 53:51 [hlavné] INFO com.baeldung.aspectj.AccountAspect - Výber ammout: 5 2016 -11-15 22:53:51 [hlavný] INFO com.baeldung.aspectj.AccountAspect - Zostatok po výbere: 15 2016-11-15 22:53:51 [hlavný] INFO com.baeldung.aspectj.AccountAspect - Zostatok pred výber: 20 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Výber ammout: 100 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Výber bol odmietnutý! 2016-11-15 22:53:51 [hlavné] INFO com.baeldung.aspectj.AccountAspect - Zostatok po výbere: 20

6. Postkompilované tkanie

Postkompilované tkanie (niekedy sa tiež nazýva binárne tkanie) sa používa na tkanie existujúcich súborov triedy a súborov JAR. Rovnako ako pri tkaní v čase kompilácie, aspekty používané na tkanie môžu byť v zdrojovej alebo binárnej forme a môžu byť tkané aspektmi.

Aby sme to mohli urobiť pomocou Mojo's AspectJ Maven Plugin, musíme urobiť nastavenie všetkých súborov JAR, ktoré by sme chceli vpliesť do konfigurácie pluginu:

   org.skupina tkať org.otvorná skupina gen 

Súbory JAR obsahujúce triedy, ktoré sa majú tkať, musia byť uvedené ako v projekte Maven a uvedený ako v doplnku AspectJ Maven.

7. Tkanie v čase načítania

Load-time tkanie je jednoducho binárne tkanie odložené až do okamihu, keď zavádzač triedy načíta súbor triedy a definuje triedu na JVM.

Na podporu tohto je potrebný jeden alebo viac „nakladačov triedy tkania“. Tieto sú buď poskytované výslovne prostredím run-time, alebo povolené pomocou „agenta tkania“.

7.1. Povolenie tkania v režime načítania

Tkanie času načítania AspectJ je možné povoliť pomocou agenta AspectJ, ktorý sa môže zapojiť do procesu načítania triedy a tkať všetky typy predtým, ako sú definované vo VM. Zadávame javaagent možnosť JVM -javaagent: pathto / aspectjweaver.jar alebo pomocou pluginu Maven nakonfigurujte javaagent :

 org.apache.maven.plugins maven-surefire-plugin 2.10 -javaagent: "$ {settings.localRepository}" / org / aspectj / aspectjweaver / $ {aspectj.version} / aspectjweaver - $ {aspectj.version} .jar pravda vždy 

7.2. Konfigurácia Weaver

Agent tkania v čase načítania AspectJ je konfigurovaný pomocou aop.xml súbory. Hľadá sa jeden alebo viac aop.xml súbory na triednej ceste v META-INF adresár a agreguje obsah, aby sa určila konfigurácia tkáča.

An aop.xml súbor obsahuje dve kľúčové sekcie:

  • Aspekty: definuje jeden alebo viac aspektov tkáča a riadi, ktoré aspekty sa majú použiť v procese tkania. The aspekty prvok môže voliteľne obsahovať jeden alebo viac zahrnúť a vylúčiť prvky (na tkanie sa štandardne používajú všetky definované aspekty)
  • Tkáč: definuje možnosti tkáča pre tkáča a špecifikuje množinu typov, ktoré by mali byť tkané. Ak nie sú zadané žiadne prvky zahrnutia, budú tkané všetky typy viditeľné pre tkáča

Nakonfigurujme aspekt pre tkáča:

Ako vidíme, nakonfigurovali sme aspekt, ktorý ukazuje na AccountAspecta iba zdrojový kód v com.baeldung.aspectj balíček bude tkaný AspectJ.

8. Anotácia aspektov

Okrem známeho štýlu deklarácie aspektu založeného na kóde AspectJ, AspectJ 5 podporuje aj štýl deklarácie aspektu založený na anotáciách. Množinu anotácií, ktoré podporujú tento štýl vývoja, neformálne nazývame „@AspectJ”Anotácie.

Vytvorme anotáciu:

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

Používame @ Zabezpečené anotácia na povolenie alebo zakázanie metódy:

verejná trieda SecuredMethod {@Secured (isLocked = true) public void lockedMethod () {} @Secured (isLocked = false) public void unlockedMethod () {}}

Ďalej pridáme aspekt pomocou anotačného štýlu AspectJ a skontrolujeme povolenie na základe atribútu anotácie @Secured:

@Aspect verejná trieda SecuredMethodAspect {@Pointcut ("@ annotation (zabezpečené)") public void callAt (zabezpečené zabezpečené) {} @Around ("callAt (zabezpečené)") verejný objekt okolo (ProceedingJoinPoint pjp, zabezpečené zabezpečené) hodí Throwable {návrat secure.isLocked ()? null: pjp.proceed (); }}

Ak sa chcete dozvedieť viac podrobností o štýle anotácií AspectJ, môžete si pozrieť nasledujúci odkaz.

Ďalej tkáme našu triedu a aspekt pomocou nástroja na načítanie a načítanie času aop.xml pod META-INF priečinok:

Nakoniec pridáme test jednotky a skontrolujeme výsledok:

@ Test public void testMethod () vyvolá výnimku {služba SecuredMethod = nová SecuredMethod (); service.unlockedMethod (); service.lockedMethod (); }

Keď spustíme testovacie prípady, môžeme skontrolovať výstup z konzoly a overiť, či sme náš aspekt a triedu úspešne pretkali do zdrojového kódu:

[INFO] Pripojte bod „method-call (void com.baeldung.aspectj.SecuredMethod.unlockedMethod ())“ v type „com.baeldung.aspectj.test.SecuredMethodTest“ (SecuredMethodTest.java:11) odporúčaný radou od „ com.baeldung.aspectj.SecuredMethodAspect '(SecuredMethodAspect.class (z SecuredMethodAspect.java)) 2016-11-15 22:53:51 [hlavné] INFO com.baeldung.aspectj.SecuredMethod - unlockedMethod 2016-11-15 22:53 : 51 [main] INFO cbaspectj.SecuredMethodAspect - public void com.baeldung.aspectj.SecuredMethod.lockedMethod () je uzamknutý

9. Záver

V tomto článku sme sa venovali úvodným konceptom o AspectJ. Podrobnosti nájdete na domovskej stránke AspectJ.

Zdrojový kód tohto článku nájdete na GitHub.