Sammenligning av Spring AOP og AspectJ

1. Introduksjon

Det er flere tilgjengelige AOP-biblioteker i dag, og disse må kunne svare på en rekke spørsmål:

  • Er den kompatibel med den eksisterende eller nye applikasjonen min?
  • Hvor kan jeg implementere AOP?
  • Hvor raskt integreres det med applikasjonen min?
  • Hva er ytelsen overhead?

I denne artikkelen vil vi se på å svare på disse spørsmålene og introdusere Spring AOP og AspectJ - de to mest populære AOP-rammene for Java.

2. AOP-konsepter

Før vi begynner, la oss gjøre en rask, høyt nivå gjennomgang av vilkår og kjernekonsepter:

  • Aspekt - en standard kode / funksjon som er spredt over flere steder i applikasjonen og vanligvis er forskjellig fra den faktiske forretningslogikken (for eksempel transaksjonsadministrasjon). Hvert aspekt fokuserer på en spesifikk tverrgående funksjonalitet
  • Joinpoint - det er et bestemt punkt under gjennomføring av programmer som metodeutførelse, konstruktøranrop eller feltoppgave
  • Råd - handlingen som er tatt av aspektet i et bestemt sammenføyningspunkt
  • Pointcut - et vanlig uttrykk som samsvarer med et joinpoint. Hver gang et tilknytningspunkt samsvarer med et snarvei, utføres et spesifisert råd tilknyttet det snarveien
  • Veving - prosessen med å knytte aspekter til målrettede objekter for å lage et anbefalt objekt

3. Spring AOP og AspectJ

La oss nå diskutere Spring AOP og AspectJ over en rekke akser - for eksempel evner, mål, veving, intern struktur, sammenføyningspunkter og enkelhet.

3.1. Evner og mål

Enkelt sagt, Spring AOP og AspectJ har forskjellige mål.

Spring AOP har som mål å gi en enkel AOP-implementering på tvers av Spring IoC for å løse de vanligste problemene som programmerere står overfor. Det er ikke ment som en komplett AOP-løsning - den kan bare brukes på bønner som administreres av en Spring container.

På den andre siden, AspectJ er den originale AOP-teknologien som tar sikte på å gi en komplett AOP-løsning. Det er mer robust, men også betydelig mer komplisert enn Spring AOP. Det er også verdt å merke seg at AspectJ kan brukes på alle domeneobjekter.

3.2. Veving

Både AspectJ og Spring AOP bruker forskjellige typer veving som påvirker deres atferd med hensyn til ytelse og brukervennlighet.

AspectJ bruker tre forskjellige typer veving:

  1. Veving av kompileringstid: AspectJ-kompilatoren tar både kildekoden til vårt aspekt og applikasjonen som input og produserer en vevd klassefiler som utdata
  2. Veving etter kompilering: Dette er også kjent som binær veving. Den brukes til å veve eksisterende klassefiler og JAR-filer med våre aspekter
  3. Veving i lastetid: Dette er akkurat som den tidligere binære vevingen, med en forskjell at vevingen utsettes til en klasselaster laster klassefilene til JVM

For mer inngående informasjon om AspectJ, gå videre til denne artikkelen.

Siden AspectJ bruker kompileringstid og veving av klasselastetid, Spring AOP bruker runtime veving.

Med runtime-veving veves aspektene under utførelsen av applikasjonen ved hjelp av proxyer for det målrettede objektet - ved hjelp av enten JDK dynamisk proxy eller CGLIB proxy (som blir diskutert i neste punkt):

3.3. Intern struktur og anvendelse

Spring AOP er et proxy-basert AOP-rammeverk. Dette betyr at for å implementere aspekter til målobjektene, vil det opprette fullmakter til det objektet. Dette oppnås på en av to måter:

  1. JDK dynamisk proxy - den foretrukne måten for Spring AOP. Når det målrettede objektet implementerer til og med ett grensesnitt, vil JDK dynamisk proxy brukes
  2. CGLIB-proxy - hvis målobjektet ikke implementerer et grensesnitt, kan CGLIB-proxy brukes

Vi kan lære mer om Spring AOP-proxy-mekanismer fra de offisielle dokumentene.

AspectJ, derimot, gjør ikke noe på kjøretid ettersom klassene er samlet direkte med aspekter.

Og i motsetning til Spring AOP, krever det ingen designmønstre. For å veve aspektene til koden, introduserer den kompilatoren kjent som AspectJ-kompilator (ajc), hvor vi kompilerer programmet vårt og kjører det ved å levere et lite (<100K) kjøretidsbibliotek.

3.4. Joinpoints

I avsnitt 3.3 viste vi at Spring AOP er basert på proxy-mønstre. På grunn av dette må den underklasse den målrettede Java-klassen og bruke tverrgående bekymringer tilsvarende.

Men det kommer med en begrensning. Vi kan ikke bruke tverrgående bekymringer (eller aspekter) på tvers av klasser som er "endelige" fordi de ikke kan overstyres, og det vil dermed føre til et unntak for kjøretid.

Det samme gjelder for statiske og endelige metoder. Våraspekter kan ikke brukes på dem fordi de ikke kan overstyres. Derfor spring AOP på grunn av disse begrensningene, støtter bare sammenkoblingspunkter for metodeutførelse.

Derimot, AspectJ vever de kryssende bekymringene direkte i den faktiske koden før kjøretid. I motsetning til Spring AOP, krever det ikke å underklasse det målrettede objektet og støtter dermed også mange andre tilknytningspunkter. Følgende er sammendraget av støttede tilknytningspunkter:

JoinpointVår AOP-støttetAspectJ støttes
MetodeanropNeiJa
MetodeutførelseJaJa
KonstruktøranropNeiJa
KonstruktørutførelseNeiJa
Statisk initialisering av utførelseNeiJa
Initialisering av objektNeiJa
FeltreferanseNeiJa
FeltoppgaveNeiJa
Utførelse av behandlerNeiJa
RådgjennomføringNeiJa

Det er også verdt å merke seg at i vår AOP blir ikke aspekter brukt på metoden som kalles i samme klasse.

Det er åpenbart fordi når vi kaller en metode innen samme klasse, så kaller vi ikke metoden for proxyen som Spring AOP leverer. Hvis vi trenger denne funksjonaliteten, må vi definere en egen metode i forskjellige bønner, eller bruke AspectJ.

3.5. Enkelhet

Spring AOP er åpenbart enklere fordi den ikke introduserer noen ekstra kompilator eller vever mellom byggeprosessen vår. Den bruker runtime-veving, og integreres derfor sømløst med vår vanlige byggeprosess. Selv om det ser enkelt ut, fungerer det bare med bønner som administreres av Spring.

For å bruke AspectJ må vi imidlertid introdusere AspectJ-kompilatoren (ajc) og pakke alle bibliotekene våre på nytt (med mindre vi bytter til veving etter kompilering eller lastetid).

Dette er selvfølgelig mer komplisert enn førstnevnte - fordi det introduserer AspectJ Java Tools (som inkluderer en kompilator (ajc), en feilsøking (ajdb), en dokumentasjonsgenerator (ajdoc), en programstruktur nettleser (ajbrowser)) som vi trenger å integrere med enten vår IDE eller byggeverktøyet.

3.6. Opptreden

Når det gjelder ytelse, veving av kompilering er mye raskere enn veving i kjøretid. Spring AOP er et proxybasert rammeverk, så det opprettes fullmakter på tidspunktet for oppstart av applikasjonen. Det er også noen flere metodeinnkallelser per aspekt, noe som påvirker ytelsen negativt.

På den annen side fletter AspectJ aspektene inn i hovedkoden før applikasjonen kjøres, og det er dermed ingen ekstra kjøretidskostnader, i motsetning til Spring AOP.

Av disse grunner antyder referanseverdiene at AspectJ er nesten rundt 8 til 35 ganger raskere enn AOP for våren.

4. Oppsummering

Denne raske tabellen oppsummerer nøkkelforskjellene mellom Spring AOP og AspectJ:

Vår AOPAspectJ
Implementert i ren JavaImplementert ved hjelp av utvidelser av Java programmeringsspråk
Ingen behov for egen kompileringsprosessTrenger AspectJ-kompilator (ajc) med mindre LTW er konfigurert
Bare kjøretid veving er tilgjengeligRuntime-veving er ikke tilgjengelig. Støtter veving av kompileringstid, etterkompilering og lastetid
Mindre kraftig - støtter bare veving på metodenivåMer kraftfull - kan veve felt, metoder, konstruktører, statiske initialiserere, endelig klasse / metoder, etc ...
Kan bare implementeres på bønner som administreres av Spring containerKan implementeres på alle domeneobjekter
Støtter bare snarveier for metodeutførelseStøtt alle punktkutt
Fullmakter opprettes av målrettede objekter, og aspekter brukes på disse fullmakteneAspekter veves direkte inn i koden før applikasjonen kjøres (før kjøretid)
Mye tregere enn AspectJBedre ytelse
Lett å lære og brukeForholdsvis mer komplisert enn Spring AOP

5. Velge riktig ramme

Hvis vi analyserer alle argumentene i denne delen, begynner vi å forstå at det ikke er det ene rammeverket som er bedre enn et annet.

Enkelt sagt, valget avhenger sterkt av våre krav:

  • Rammeverk: Hvis applikasjonen ikke bruker Spring framework, har vi ikke annet valg enn å slippe ideen om å bruke Spring AOP fordi den ikke klarer noe som er utenfor rekkevidden til vårcontaineren. Imidlertid, hvis applikasjonen vår er opprettet helt ved hjelp av Spring framework, kan vi bruke Spring AOP ettersom det er greit å lære og bruke
  • Fleksibilitet: Gitt begrenset støttepunkt for sammenkobling, er Spring AOP ikke en komplett AOP-løsning, men den løser de vanligste problemene som programmerere står overfor. Selv om vi ønsker å grave dypere og utnytte AOP til den maksimale muligheten og vil ha støtte fra et bredt utvalg av tilgjengelige tilknytningspunkter, er AspectJ valget
  • Ytelse: Hvis vi bruker begrensede aspekter, er det trivielle ytelsesforskjeller. Men det er noen ganger tilfeller når en applikasjon har mer enn titusenvis av aspekter. Vi ønsker ikke å bruke runtime-veving i slike tilfeller, så det ville være bedre å velge AspectJ. AspectJ er kjent for å være 8 til 35 ganger raskere enn Spring AOP
  • Best of Both: Begge disse rammene er fullt kompatible med hverandre. Vi kan alltid dra nytte av Spring AOP når det er mulig, og fortsatt bruke AspectJ for å få støtte for sammenkoblingspunkter som ikke støttes av tidligere

6. Konklusjon

I denne artikkelen analyserte vi både Spring AOP og AspectJ, på flere viktige områder.

Vi sammenlignet de to tilnærmingene til AOP, både når det gjelder fleksibilitet og hvor lett de passer med applikasjonen vår.


$config[zx-auto] not found$config[zx-overlay] not found