CDI Interceptor vs Spring AspectJ

1. Introduktion

Interceptor-mønsteret bruges generelt til at tilføje ny tværgående funktionalitet eller logik i en applikation og har solid understøttelse i et stort antal biblioteker.

I denne artikel dækker vi og kontrasterer to af disse store biblioteker: CDI-interceptors og Spring AspectJ.

2. Opsætning af CDI Interceptor-projekt

CDI understøttes officielt til Jakarta EE, men nogle implementeringer understøtter brug af CDI i Java SE-miljø. Svejsning kan betragtes som et eksempel på CDI-implementering, som understøttes i Java SE.

For at kunne bruge CDI skal vi importere svejsebiblioteket i vores POM:

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

Det seneste Weld-bibliotek kan findes i Maven-arkivet.

Lad os nu oprette en simpel interceptor.

3. Introduktion til CDI Interceptor

For at udpege klasser, vi havde brug for at opfange, lad os oprette interceptorbinding:

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

Når vi har defineret interceptorbindingen, skal vi definere den aktuelle interceptorimplementering:

@Audited @Interceptor public class AuditedInterceptor {public static boolean calledBefore = false; offentlig statisk boolsk kaldet Efter = falsk; @AroundInvoke public Object auditMethod (InvocationContext ctx) kaster undtagelse {calledBefore = true; Objektresultat = ctx.proceed (); calledAfter = sand; returresultat }}

Hver @AroundInvoke metoden tager en javax.interceptor.InvocationContext argument, returnerer a java.lang.Objektog kan kaste et Undtagelse.

Og så, når vi kommenterer en metode med den nye @Revidere interface, auditMethode vil blive påberåbt først, og først derefter fortsætter målmetoden også.

4. Anvend CDI Interceptor

Lad os anvende den oprettede interceptor på en eller anden forretningslogik:

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

Vi har oprettet denne enkle tjeneste og kommenteret den metode, vi ønskede at opfange med @Audited kommentar.

For at aktivere CDI-interceptoren skal man angive det fulde klassenavn i bønner.xml fil, der er placeret i META-INF vejviser:

  com.baeldung.interceptor.AuditedInterceptor 

At validere denne interceptor har faktisk fungeret lad os nu køre følgende test:

offentlig klasse TestInterceptor {Weld svejsning; WeldContainer container; @Før offentlig ugyldig init () {svejsning = ny svejsning (); container = weld.initialize (); } @Efter offentlig lukket nedlukning () {weld.shutdown (); } @Test offentlig ugyldighed givenTheService_whenMethodAndInterceptorExecuted_thenOK () {SuperService superService = container.select (SuperService.class) .get (); Strengkode = "123456"; superService.deliverService (kode); Assert.assertTrue (AuditedInterceptor.calledBefore); Assert.assertTrue (AuditedInterceptor.calledAfter); }}

I denne hurtige test får vi først bønnen SuperService fra containeren, påkald derefter forretningsmetoden levere service på det, og kontroller den interceptor AuditedInterceptor blev faktisk kaldt ved at validere dens tilstandsvariabler.

Det har vi også @Før og @Efter bemærkede metoder, hvor vi initialiserer og lukker henholdsvis Svejsebeholder.

5. CDI-overvejelser

Vi kan påpege følgende fordele ved CDI-interceptorer:

  • Det er en standardfunktion i Jakarta EE-specifikationen
  • Nogle CDI-implementeringsbiblioteker kan bruges i Java SE
  • Kan bruges, når vores projekt har alvorlige begrænsninger på tredjepartsbiblioteker

Ulemperne ved CDI-interceptorerne er følgende:

  • Tæt kobling mellem klasse med forretningslogik og interceptor
  • Svært at se, hvilke klasser der opfanges i projektet
  • Mangel på fleksibel mekanisme til at anvende interceptors på en gruppe metoder

6. Spring AspectJ

Spring understøtter en lignende implementering af interceptor-funktionalitet ved hjælp af AspectJ-syntaks også.

Først skal vi tilføje følgende Spring- og AspectJ-afhængigheder til POM:

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

De seneste versioner af Spring-sammenhæng, aspectjweaver, findes i Maven-arkivet.

Vi kan nu oprette et simpelt aspekt ved hjælp af AspectJ-kommentarsyntaks:

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

Vi skabte et aspekt, der gælder for alle metoder til SpringSuperService klasse - som for enkelhedens skyld ser sådan ud:

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

7. Spring AspectJ Aspect Anvend

For at validere dette aspekt virkelig gælder for tjenesten, lad os skrive følgende enhedstest:

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

I denne test indsprøjter vi vores service, kalder metoden og kontrollerer resultatet.

Sådan ser konfigurationen ud:

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

Et vigtigt aspekt her i @EnableAspectJAutoProxy annotation - som muliggør understøttelse af håndtering af komponenter markeret med AspectJ's @Aspect kommentar, svarende til funktionalitet, der findes i Spring's XML-element.

8. Spring AspectJ Overvejelser

Lad os påpege et par af fordelene ved at bruge Spring AspectJ:

  • Interceptors afkobles fra forretningslogikken
  • Interceptors kan drage fordel af afhængighedsinjektion
  • Interceptor har alle konfigurationsoplysningerne i sig selv
  • Tilføjelse af nye interceptors ville ikke kræve en udvidelse af eksisterende kode
  • Interceptor har fleksibel mekanisme til at vælge, hvilke metoder der skal opsnappes
  • Kan bruges uden Jakarta EE

Og selvfølgelig et par af ulemperne:

  • Du skal kende AspectJ-syntaksen for at udvikle interceptors
  • Læringskurven for AspectJ-interceptorerne er højere end for CDI-interceptorerne

9. CDI Interceptor vs Spring AspectJ

Hvis dit nuværende projekt bruger Spring, er det et godt valg at overveje Spring AspectJ.

Hvis du bruger en fuldt anvendt applikationsserver, eller dit projekt ikke bruger Spring (eller andre rammer, f.eks. Google Guice) og strengt taget er Jakarta EE, er der intet tilbage end at vælge CDI-interceptor.

10. Konklusion

I denne artikel har vi dækket to implementeringer af interceptor mønster: CDI interceptor og Spring AspectJ. Vi har dækket fordele og ulemper hver af dem.

Kildekoden til eksempler på denne artikel kan findes i vores lager på GitHub.


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