CDI Interceptor vs Spring AspectJ

1. Introduksjon

Interceptor-mønsteret brukes vanligvis til å legge til ny, tverrgående funksjonalitet eller logikk i en applikasjon, og har solid støtte i et stort antall biblioteker.

I denne artikkelen vil vi dekke og kontrastere to av disse store bibliotekene: CDI-interceptors og Spring AspectJ.

2. Oppsett av CDI Interceptor Project

CDI støttes offisielt for Jakarta EE, men noen implementeringer gir støtte for bruk av CDI i Java SE-miljø. Sveis kan betraktes som et eksempel på CDI-implementering som støttes i Java SE.

For å kunne bruke CDI må vi importere sveisebiblioteket i POM:

 org.jboss.weld.se weld-se-core 3.0.5.Final 

Det siste Weld-biblioteket finnes i Maven-arkivet.

La oss nå lage en enkel avlytter.

3. Introduksjon av CDI Interceptor

For å utpeke klasser vi trengte å fange opp, la oss lage interceptorbinding:

@InterceptorBinding @Target ({METODE, TYPE}) @Retention (RUNTIME) offentlig @interface revidert {}

Etter at vi har definert interceptorbindingen, må vi definere den faktiske interceptorimplementeringen:

@Audited @Interceptor offentlig klasse AuditedInterceptor {offentlig statisk boolean calledBefore = false; offentlig statisk boolsk kalt After = false; @AroundInvoke public Object auditMethod (InvocationContext ctx) kaster Unntak {calledBefore = true; Objektresultat = ctx.proceed (); calledAfter = true; returresultat; }}

Hver @AroundInvoke metoden tar en javax.interceptor.InvocationContext argument, returnerer a java.lang.Objekt, og kan kaste en Unntak.

Og så når vi kommenterer en metode med den nye @Revidere grensesnitt, revisjonsmetode vil bli påkalt først, og først deretter fortsetter målmetoden også.

4. Bruk CDI Interceptor

La oss bruke den opprettet interceptor på noen forretningslogikk:

offentlig klasse SuperService {@Audited public String deliverService (String uid) {return uid; }}

Vi har opprettet denne enkle tjenesten og kommentert metoden vi ønsket å få med @Audited kommentar.

For å aktivere CDI-interceptor må du spesifisere hele klassenavnet i bønner.xml filen, som ligger i META-INF katalog:

  com.baeldung.interceptor.AuditedInterceptor 

Å validere at interceptor har virkelig fungert la oss nå kjøre følgende test:

offentlig klasse TestInterceptor {Sveisesveis; WeldContainer container; @Før offentlig ugyldig init () {sveis = ny sveis (); container = weld.initialize (); } @Efter offentlig ugyldig nedleggelse () {weld.shutdown (); } @Test offentlig ugyldig gittTheService_whenMethodAndInterceptorExecuted_thenOK () {SuperService superService = container.select (SuperService.class) .get (); Strengkode = "123456"; superService.deliverService (kode); Assert.assertTrue (AuditedInterceptor.calledBefore); Assert.assertTrue (AuditedInterceptor.calledAfter); }}

I denne raske testen får vi først bønnen SuperService fra containeren, og påkall deretter forretningsmetoden deliverService på den og sjekk avlyssneren AuditedInterceptor ble faktisk kalt ved å validere tilstandsvariablene.

Det har vi også @Før og @Etter merkede metoder der vi initialiserer og stenger henholdsvis Sveisebeholder.

5. Hensyn til CDI

Vi kan påpeke følgende fordeler med CDI-avlyttere:

  • Det er en standard funksjon i Jakarta EE spesifikasjon
  • Noen CDI-implementeringsbiblioteker kan brukes i Java SE
  • Kan brukes når prosjektet vårt har alvorlige begrensninger på tredjepartsbiblioteker

Ulempene med CDI-avlytterne er følgende:

  • Tett kobling mellom klasse med forretningslogikk og interceptor
  • Vanskelig å se hvilke klasser som blir fanget opp i prosjektet
  • Mangel på fleksibel mekanisme for å anvende avlyttere på en gruppe metoder

6. VåraspektJ

Spring støtter en lignende implementering av interceptor-funksjonalitet ved å bruke AspectJ syntaks også.

Først må vi legge til følgende vår- og AspectJ-avhengigheter til POM:

 org.springframework spring-context 5.2.8.RELEASE org.aspectj aspectjweaver 1.9.2 

De nyeste versjonene av vårkontekst, aspectjweaver, finnes i Maven-arkivet.

Vi kan nå lage et enkelt aspekt ved hjelp av AspectJ-merknadssyntaks:

@Aspect offentlig klasse SpringTestAspect {@Autowired privat listeakkumulator; @Around ("utførelse (* com.baeldung.spring.service.SpringSuperService. * (..))") offentlig Object auditMethod (ProceedingJoinPoint jp) kaster Throwable {String methodName = jp.getSignature (). GetName (); accumulator.add ("Call to" + methodName); Objekt obj = jp.proceed (); accumulator.add ("Metode kalt vellykket:" + methodName); retur obj; }}

Vi opprettet et aspekt som gjelder alle metodene for SpringSuperService klasse - som for enkelhets skyld ser slik ut:

offentlig klasse SpringSuperService {public String getInfoFromService (String code) {returkode; }}

7. Spring AspectJ Aspect Apply

For å validere dette aspektet virkelig gjelder tjenesten, la oss skrive følgende enhetstest:

@RunWith (SpringRunner.class) @ContextConfiguration (klasser = {AppConfig.class}) offentlig klasse TestSpringInterceptor {@Autowired SpringSuperService springSuperService; @Autowired privat liste akkumulator; @Test offentlig ugyldig givenService_whenServiceAndAspectExecuted_thenOk () {String code = "123456"; Strengresultat = springSuperService.getInfoFromService (kode); Assert.assertThat (accumulator.size (), er (2)); Assert.assertThat (accumulator.get (0), er ("Call to getInfoFromService")); Assert.assertThat (accumulator.get (1), er ("Metode kalt vellykket: getInfoFromService")); }}

I denne testen injiserer vi vår tjeneste, kaller metoden og sjekker resultatet.

Slik ser konfigurasjonen ut:

@Configuration @EnableAspectJAutoProxy public class AppConfig {@Bean public SpringSuperService springSuperService () {return new SpringSuperService (); } @Bean public SpringTestAspect springTestAspect () {return new SpringTestAspect (); } @Bean offentlig liste getAccumulator () {returner ny ArrayList (); }}

Et viktig aspekt her i @EnableAspectJAutoProxy kommentar - som muliggjør støtte for håndtering av komponenter merket med AspectJ @Aspect kommentar, som ligner på funksjonaliteten i Spring's XML-element.

8. VåraspektJ Hensyn

La oss peke på noen av fordelene ved å bruke Spring AspectJ:

  • Avskjærere er frikoblet fra forretningslogikken
  • Avlyttere kan dra nytte av avhengighetsinjeksjon
  • Interceptor har all konfigurasjonsinformasjonen i seg selv
  • Å legge til nye avlyttere vil ikke kreve utvidelse av eksisterende kode
  • Interceptor har fleksibel mekanisme for å velge hvilke metoder som skal fanges opp
  • Kan brukes uten Jakarta EE

Og selvfølgelig noen av ulempene:

  • Du må kjenne AspectJ-syntaksen for å utvikle interceptors
  • Læringskurven for AspectJ-avlytterne er høyere enn for CDI-avlytterne

9. CDI Interceptor vs Spring AspectJ

Hvis ditt nåværende prosjekt bruker Spring, er det et godt valg å vurdere Spring AspectJ.

Hvis du bruker en fullverdig applikasjonsserver, eller hvis prosjektet ditt ikke bruker Spring (eller andre rammer, f.eks. Google Guice) og er strengt Jakarta EE, er det ingenting igjen enn å velge CDI-avlytter.

10. Konklusjon

I denne artikkelen har vi dekket to implementeringer av interceptor mønster: CDI interceptor og Spring AspectJ. Vi har dekket fordeler og ulemper hver av dem.

Kildekoden for eksempler på denne artikkelen finner du i vårt depot på GitHub.


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