Introduktion til AspectJ

1. Introduktion

Denne artikel er en hurtig og praktisk introduktion til AspectJ.

Først viser vi, hvordan du aktiverer aspektorienteret programmering, og derefter fokuserer vi på forskellen mellem kompileringstid, postkompilering og indlæsningstid.

Lad os starte med en kort introduktion af aspektorienteret programmering (AOP) og AspectJs basics.

2. Oversigt

AOP er et programmeringsparadigme, der sigter mod at øge modulariteten ved at tillade adskillelse af tværgående bekymringer. Det gør det ved at tilføje yderligere adfærd til eksisterende kode uden at ændre selve koden. I stedet erklærer vi separat, hvilken kode der skal ændres.

AspectJ implementerer både bekymringer og vævning af tværgående bekymringer ved hjælp af udvidelser af Java-programmeringssprog.

3. Maven-afhængigheder

AspectJ tilbyder forskellige biblioteker afhængigt af dets anvendelse. Vi kan finde Maven-afhængigheder under gruppe org.aspectj i Maven Central-arkivet.

I denne artikel fokuserer vi på afhængigheder, der er nødvendige for at oprette aspekter og Weaver ved hjælp af kompileringstid, postkompilering og indlæsningstid.

3.1. AspectJ Runtime

Når du kører et AspectJ-program, skal klassestien indeholde klasser og aspekter sammen med AspectJ runtime-biblioteket aspectjrt.jar:

 org.aspectj aspectjrt 1.8.9 

Denne afhængighed er tilgængelig på Maven Central.

3.2. AspectJWeaver

Udover AspectJ runtime afhængighed skal vi også medtage aspectjweaver.jar at introducere råd til Java-klassen ved indlæsningstid:

 org.aspectj aspectjweaver 1.8.9 

Afhængigheden er også tilgængelig på Maven Central.

4. Aspect Creation

AspectJ leverer en implementering af AOP og har tre kernebegreber:

  • Deltag i Point
  • Pointcut
  • Råd

Vi demonstrerer disse begreber ved at oprette et simpelt program til validering af en brugerkontosaldo.

Lad os først oprette en Konto klasse med en given saldo og en metode til at trække:

offentlig klassekonto {int balance = 20; offentlig boolsk tilbagetrækning (int-beløb) {if (balance <beløb) {return false; } balance = balance - beløb; returner sandt; }}

Vi opretter en AccountAspect.aj fil for at logge kontooplysninger og for at validere kontosaldoen (bemærk, at AspectJ-filer slutter med en “.aj”Filtypenavn):

offentligt aspekt AccountAspect {final int MIN_BALANCE = 10; pointcut callWithDraw (int beløb, konto acc): call (boolsk konto.withdraw (int)) && args (beløb) && target (acc); før (int beløb, konto acc): callWithDraw (beløb, acc) {} boolsk rundt (int beløb, konto acc): callWithDraw (beløb, acc) {hvis (iht. balance <beløb) {returner falsk; } returner fortsæt (beløb, akk); } efter (int beløb, kontosaldo): callWithDraw (beløb, saldo) {}}

Som vi kan se, har vi tilføjet en genvejstast til tilbagetrækningsmetoden og oprettede tre rådgiver der henviser til det definerede genvejstast.

For at forstå følgende introducerer vi følgende definitioner:

  • Aspekt: En modularisering af et problem, der skærer på tværs af flere objekter. Hvert aspekt fokuserer på en bestemt tværgående funktionalitet
  • Deltag i punkt: Et punkt under udførelsen af ​​et script, såsom udførelsen af ​​en metode eller ejendomsadgang
  • Råd: Handling truffet af et aspekt på et bestemt tilslutningspunkt
  • Pointcut: Et regulært udtryk, der matcher sammenføjningspunkter. Et råd er forbundet med et punktudtryksudtryk og kører på et hvilket som helst tilslutningspunkt, der matcher genvejstasten

For flere detaljer om disse begreber og deres specifikke semantik, vil vi måske tjekke følgende link.

Dernæst skal vi væve aspekterne ind i vores kode. Afsnittene nedenfor vedrører tre forskellige typer vævning: vævning af kompileringstid, vævning efter kompilering og vævning af load-tid i AspectJ.

5. Vævning af kompileringstid

Den enkleste tilgang til vævning er kompileringstidsvævning. Når vi har både kildekoden til aspektet og koden, som vi bruger aspekter i, kompilerer AspectJ-kompilatoren fra kilden og producerer en vævet klassefiler som output. Derefter, efter udførelse af din kode, indlæses outputklassen til vævningsprocessen i JVM som en normal Java-klasse.

Vi kan downloade AspectJ-udviklingsværktøjerne, da det inkluderer en medfølgende AspectJ-compiler. En af AJDTs vigtigste funktioner er et værktøj til visualisering af tværgående bekymringer, hvilket er nyttigt til fejlfinding af en genvejsspecifikation. Vi visualiserer muligvis den kombinerede effekt, selv før koden implementeres.

Vi bruger Mojo's AspectJ Maven Plugin til at væve AspectJ-aspekter ind i vores klasser ved hjælp af AspectJ-kompilatoren.

 org.codehaus.mojo aspectj-maven-plugin 1.7 1.8 1.8 1.8 sandt sandt ignorere UTF-8 kompilere test-kompilere 

For flere detaljer om indstillingsreference for AspectJ-kompilatoren, vil vi måske tjekke følgende link.

Lad os tilføje nogle testcases til vores kontoklasse:

offentlig klasse AccountTest {privat konto konto; @Før offentlig ugyldighed før () {konto = ny konto (); } @Test offentlig ugyldighed given20AndMin10_whenWithdraw5_thenSuccess () {assertTrue (account.withdraw (5)); } @Test offentligt ugyldigt givet20AndMin10_whenWithdraw100_thenFail () {assertFalse (account.withdraw (100)); }}

Når vi kører testcases, betyder nedenstående tekst, der vises i konsollen, at vi med succes har vævet kildekoden:

[INFO] Deltag punkt 'metode-opkald (boolsk com.baeldung.aspectj.Account.withdraw (int))' i Type 'com.baeldung.aspectj.test.AccountTest' (AccountTest.java:20) rådes af omkring råd fra 'com.baeldung.aspectj.AccountAspect' (AccountAspect.class: 18 (from AccountAspect.aj)) [INFO] Join point 'method-call (boolean com.baeldung.aspectj.Account.withdraw (int))' in Type ' com.baeldung.aspectj.test.AccountTest '(AccountTest.java:20) rådgivet af før råd fra' com.baeldung.aspectj.AccountAspect '(AccountAspect.class: 13 (fra AccountAspect.aj)) [INFO] Deltag punkt' method-call (boolsk com.baeldung.aspectj.Account.withdraw (int)) 'in Type' com.baeldung.aspectj.test.AccountTest '(AccountTest.java:20) rådes af efter råd fra' com.baeldung.aspectj .AccountAspect '(AccountAspect.class: 26 (from AccountAspect.aj)) 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Saldo før tilbagetrækning: 20 2016-11-15 22: 53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Træk ammout: 5 2016 -11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Saldo efter tilbagetrækning: 15 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Balance før tilbagetrækning: 20 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Træk ammout: 100 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Tilbagetrækning afvist! 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Saldo efter tilbagetrækning: 20

6. Vævning efter kompilering

Vævning efter kompilering (også undertiden kaldet binær vævning) bruges til at væve eksisterende klassefiler og JAR-filer. Som med kompileringstidsvævning kan de aspekter, der anvendes til vævning, være i kilde- eller binær form og kan i sig selv væves af aspekter.

For at gøre dette med Mojo's AspectJ Maven Plugin skal vi konfigurere alle de JAR-filer, vi gerne vil væve i plugin-konfigurationen:

   org.agroup to-weave org.anothergroup gen 

JAR-filerne, der indeholder de klasser, der skal væves, skal være angivet som i Maven-projektet og opført som i af AspectJ Maven Plugin.

7. Vævning af belastningstid

Load-time vævning er simpelthen binær vævning udsat indtil det punkt, hvor en klasselæsser indlæser en klassefil og definerer klassen til JVM.

For at understøtte dette kræves en eller flere "vævningsklasse-læssere". Disse leveres enten eksplicit af runtime-miljøet eller aktiveres ved hjælp af et "vævemiddel".

7.1. Aktivering af Load-Time Weaving

AspectJ load-time vævning kan aktiveres ved hjælp af AspectJ agent, der kan blive involveret i klassens indlæsningsproces og væve alle typer, før de defineres i VM. Vi specificerer javaagent mulighed til JVM -javaagent: pathto / aspectjweaver.jar eller ved hjælp af Maven-plugin til at konfigurere javaagent :

 org.apache.maven.plugins maven-surefire-plugin 2.10 -javaagent: "$ {settings.localRepository}" / org / aspectj / aspectjweaver / $ {aspectj.version} / aspectjweaver - $ {aspectj.version} .jar altid sandt 

7.2. Konfigurationsvæver

AspectJs load-time vævemiddel konfigureres ved hjælp af aop.xml filer. Det ser efter en eller flere aop.xml filer på klassestien i META-INF katalog og aggregerer indholdet for at bestemme væverkonfigurationen.

En aop.xml filen indeholder to nøglesektioner:

  • Aspekter: definerer et eller flere aspekter til væveren og styrer, hvilke aspekter der skal bruges i vævningsprocessen. Det aspekter element kan eventuelt indeholde en eller flere omfatte og udelukke elementer (som standard bruges alle definerede aspekter til vævning)
  • Væver: definerer væverindstillinger til væveren og specificerer det sæt typer, der skal væves. Hvis der ikke er angivet nogen inkluderende elementer, væves alle typer, der er synlige for væveren

Lad os konfigurere et aspekt til væveren:

Som vi kan se, har vi konfigureret et aspekt, der peger på AccountAspect, og kun kildekoden i com.baeldung.aspectj pakke væves af AspectJ.

8. Kommentarer om aspekter

Ud over den velkendte AspectJ-kodebaserede stil med aspektdeklaration understøtter AspectJ 5 også en annoteringsbaseret stil med aspektdeklaration. Vi kalder uformelt det sæt af kommentarer, der understøtter denne udviklingsstil, ”@AspectJ”Kommentarer.

Lad os oprette en kommentar:

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

Vi bruger @Sikret kommentar for at aktivere eller deaktivere en metode:

offentlig klasse SecuredMethod {@Secured (isLocked = true) public void lockedMethod () {} @Secured (isLocked = false) public void unlockedMethod () {}}

Dernæst tilføjer vi et aspekt ved hjælp af AspectJ-kommentar-stil og kontrollerer tilladelsen baseret på attributten for @Secured-kommentaren:

@Aspect public class SecuredMethodAspect {@Pointcut ("@ annotation (secure)") public void callAt (Secured secure) {} @Around ("callAt (secure)") public Object around (ProceedingJoinPoint pjp, Secured secure) throw Throwable {return) secure.isLocked ()? null: pjp.proceed (); }}

For flere detaljer om AspectJ-annoteringsstil kan vi tjekke følgende link.

Dernæst væver vi vores klasse og aspekt ved hjælp af load-time væver og put aop.xml under META-INF folder:

Endelig tilføjer vi enhedstest og kontrollerer resultatet:

@Test offentlig ugyldig testMethod () kaster undtagelse {SecuredMethod service = ny SecuredMethod (); service.unlockedMethod (); service.lockedMethod (); }

Når vi kører testsagerne, kan vi kontrollere konsoludgangen for at kontrollere, at vi med succes har vævet vores aspekt og klasse i kildekoden:

[INFO] Join point 'method-call (void com.baeldung.aspectj.SecuredMethod.unlockedMethod ())' in Type 'com.baeldung.aspectj.test.SecuredMethodTest' (SecuredMethodTest.java:11) rådgivet af omkring råd fra ' com.baeldung.aspectj.SecuredMethodAspect '(SecuredMethodAspect.class (fra SecuredMethodAspect.java)) 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.SecuredMethod - ulåstMethode 2016-11-15 22:53 : 51 [main] INFO cbaspectj.SecuredMethodAspect - public void com.baeldung.aspectj.SecuredMethod.lockedMethod () er låst

9. Konklusion

I denne artikel dækkede vi introduktionskoncepter om AspectJ. For detaljer kan du se på AspectJ-hjemmesiden.

Du kan finde kildekoden til denne artikel på GitHub.