Spring AOP - Implementazioni

La primavera supporta il @AspectJ annotation style approccio e il schema-based approccio per implementare aspetti personalizzati.

Basato su XML Schema

Gli aspetti vengono implementati utilizzando classi regolari insieme alla configurazione basata su XML.

Per utilizzare i tag dello spazio dei nomi AOP descritti in questa sezione, è necessario importare lo schema AOP a molla, descritto come segue:

<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
   
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:aop = "http://www.springframework.org/schema/aop"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
   http://www.springframework.org/schema/aop 
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

   <!-- bean definition & AOP specific configuration -->

</beans>

Dichiarare un aspetto

Un aspect viene dichiarato utilizzando il <aop:aspect> elemento, e il backing bean viene referenziato usando il ref attributo come segue.

<aop:config>
   <aop:aspect id = "myAspect" ref = "aBean">
   ...
   </aop:aspect>
</aop:config>

<bean id = "aBean" class = "...">
   ...
</bean>

Qui verrà configurato "aBean" e verrà iniettata la dipendenza proprio come qualsiasi altro bean Spring come si è visto nei capitoli precedenti.

Dichiarazione di un PointCut

UN PointCutaiuta a determinare i punti di unione (cioè i metodi) di interesse da eseguire con diversi consigli. Mentre si lavora con la configurazione basata su XML Schema, PointCut verrà definito come segue:

<aop:config>
   <aop:aspect id = "myAspect" ref = "aBean">

   <aop:PointCut id = "businessService"
      expression = "execution(* com.xyz.myapp.service.*.*(..))"/>
      ...
   </aop:aspect>
</aop:config>

<bean id = "aBean" class = "...">
   ...
</bean>

L'esempio seguente definisce un PointCut denominato "businessService" che corrisponderà all'esecuzione del metodo getName () disponibile nella classe Student nel pacchetto com.tutorialspoint.

<aop:config>
   <aop:aspect id = "myAspect" ref = "aBean">

   <aop:PointCut id = "businessService"
      expression = "execution(* com.tutorialspoint.Student.getName(..))"/>
   ...
   </aop:aspect>
</aop:config>

<bean id = "aBean" class = "...">
   ...
</bean>

Dichiarare consigli

Puoi dichiarare uno qualsiasi dei cinque consigli all'interno di un <aop: aspect> utilizzando l'elemento <aop: {ADVICE NAME}> come segue.

<aop:config>
   <aop:aspect id = "myAspect" ref = "aBean">
      <aop:PointCut id = "businessService"
         expression = "execution(* com.xyz.myapp.service.*.*(..))"/>

      <!-- a before advice definition -->
      <aop:before PointCut-ref = "businessService" 
         method = "doRequiredTask"/>

      <!-- an after advice definition -->
      <aop:after PointCut-ref = "businessService" 
         method = "doRequiredTask"/>

      <!-- an after-returning advice definition -->
      <!--The doRequiredTask method must have parameter named retVal -->
      <aop:after-returning PointCut-ref = "businessService"
         returning = "retVal"
         method = "doRequiredTask"/>

      <!-- an after-throwing advice definition -->
      <!--The doRequiredTask method must have parameter named ex -->
      <aop:after-throwing PointCut-ref = "businessService"
        throwing = "ex"
         method = "doRequiredTask"/>

      <!-- an around advice definition -->
      <aop:around PointCut-ref = "businessService" 
         method = "doRequiredTask"/>
   ...
   </aop:aspect>
</aop:config>

<bean id = "aBean" class = "...">
   ...
</bean>

Puoi usare lo stesso doRequiredTasko metodi diversi per consigli diversi. Questi metodi saranno definiti come parte del modulo di aspetto.

Basato su @AspectJ

@AspectJ fa riferimento a uno stile di dichiarazione degli aspetti come normali classi Java annotate con annotazioni Java 5. Il supporto @AspectJ viene abilitato includendo il seguente elemento nel file di configurazione basato su XML Schema.

<aop:aspectj-autoproxy/>

Dichiarare un aspetto

Le classi degli aspetti sono come qualsiasi altro bean normale e possono avere metodi e campi come qualsiasi altra classe, tranne per il fatto che verranno annotati con @Aspect come segue.

package org.xyz;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectModule {

}

Verranno configurati in XML come qualsiasi altro bean come segue.

<bean id = "myAspect" class = "org.xyz.AspectModule">
   <!-- configure properties of aspect here as normal -->
</bean>

Dichiarazione di un PointCut

UN PointCutaiuta a determinare i punti di unione (cioè i metodi) di interesse da eseguire con diversi consigli. Mentre si lavora con la configurazione basata su @AspectJ, la dichiarazione PointCut ha due parti:

  • Un'espressione PointCut che determina esattamente a quali esecuzioni del metodo siamo interessati.

  • Una firma PointCut che comprende un nome e un numero qualsiasi di parametri. Il corpo effettivo del metodo è irrilevante e in effetti dovrebbe essere vuoto.

L'esempio seguente definisce un PointCut denominato "businessService" che corrisponderà all'esecuzione di ogni metodo disponibile nelle classi nel pacchetto com.xyz.myapp.service.

import org.aspectj.lang.annotation.PointCut;

@PointCut("execution(* com.xyz.myapp.service.*.*(..))") // expression 
private void businessService() {}  // signature

L'esempio seguente definisce un PointCut denominato "getname" che corrisponderà all'esecuzione del metodo getName () disponibile nella classe Student nel pacchetto com.tutorialspoint.

import org.aspectj.lang.annotation.PointCut;

@PointCut("execution(* com.tutorialspoint.Student.getName(..))") 
private void getname() {}

Dichiarare consigli

Puoi dichiarare uno qualsiasi dei cinque consigli utilizzando le annotazioni @ {NOME-CONSIGLIO} come indicato di seguito. Ciò presuppone che abbiate già definito un metodo di firma PointCut businessService ().

@Before("businessService()")
public void doBeforeTask(){
   ...
}

@After("businessService()")
public void doAfterTask(){
   ...
}

@AfterReturning(PointCut = "businessService()", returning = "retVal")
public void doAfterReturnningTask(Object retVal){
   // you can intercept retVal here.
   ...
}

@AfterThrowing(PointCut = "businessService()", throwing = "ex")
public void doAfterThrowingTask(Exception ex){
   // you can intercept thrown exception here.
   ...
}

@Around("businessService()")
public void doAroundTask(){
   ...
}

È possibile definire PointCut in linea per qualsiasi consiglio. Di seguito è riportato un esempio per definire PointCut inline per prima del consiglio.

@Before("execution(* com.xyz.myapp.service.*.*(..))")
public doBeforeTask(){
   ...
}