Tutorial AspectJ Based AOP con Spring

0
1882

AspectJ Si riferisce ad uno stile di dichiarare aspetti come classi Java regolari annotate con le annotazioni Java 5. Il supporto AspectJ è abilitato inserendo il seguente elemento all’interno del file di configurazione basato su schema XML.

<aop:aspectj-autoproxy/>

Sarà inoltre necessario seguenti librerie AspectJ sul classpath dell’applicazione. Queste librerie sono disponibili nella directory ‘lib’ di un impianto AspectJ, altrimenti è possibile scaricarli da internet.

  • aspectjrt.jar
  • aspectjweaver.jar
  • aspectj.jar
  • aopalliance.jar

Dichiarare un aspetto

Le classi AOP sono come qualsiasi altro bean normale e possono avere metodi e campi, proprio come qualsiasi altra classe, tranne che saranno annotate con Aspect come segue:

package org.xyz;

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectModule {

}

Essi saranno configurati in XML come qualsiasi altro bean come segue:

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

Dichiarare un pointcut

Un pointcut contribuisce a determinare i punti di join (vale a dire metodi) di interesse che deve essere eseguiti con diversi advices. Mentre si lavora con configurazione basata AspectJ, la dichiarazione pointcut ha due parti:

  • Un’espressione pointcut che determina esattamente quale metodo esecuzioni ci interessa.
  • Una firma pointcut comprendente un nome e qualsiasi numero di parametri. Il corpo stesso del metodo è irrilevante e infatti deve essere vuoto.

L’esempio seguente definisce un pointcut chiamato ‘businessService’ che abbinerà l’esecuzione di ogni metodo disponibile nelle classi di sotto del 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 chiamato ‘getName’ che abbinerà l’esecuzione di getName () metodo disponibile in classe Student sotto il pacchetto com.xx.yy:

import org.aspectj.lang.annotation.Pointcut;

@Pointcut("execution(* com.xx.yy.Student.getName(..))") 
private void getname() {}

Dichiarare consigli

È possibile dichiarare qualsiasi dei cinque advices utilizzando @ {ADVICE-NAME} come indicato di seguito. Ciò presuppone che sia già stato 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 voi pointcut linea per uno dei advices. Di seguito è riportato un esempio per definire pointcut linea per advice prima:

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

AspectJ AOP Based Esempio

Per comprendere i concetti sopra citati relativi alla baseAspectJ AOP, scriviamo un esempio che attuerà alcuni dei consigli. Per scrivere il nostro esempio con alcuni advices, quindi apriamo il nostro IDE Eclipse ed seguire la seguente procedura per creare un’applicazione Spring:

Passo Descrizione
1 Creare un progetto con un nome SpringExample e creare un pacchetto com.xx.yy sotto il src cartella nel progetto creato.
2 Aggiungere librerie Spring richiesti utilizzando Aggiungi JAR esterni .
3 Aggiungere Spring AOP librerie specifiche aspectjrt.jar, aspectjweaver.jar e aspectj.jar nel progetto.
4 Creare classi Java registrazione , studenti e MainApp sotto ilpacchetto com.xx.yy.
5 Creare file di  configurazione per i Bean  beans.xml sotto la cartella src .
6 Il passo finale è quello di creare il contenuto di tutti i file Java e file di configurazione Bean ed eseguire l’applicazione come spiegato di seguito.

Ecco il contenuto della Logging.java file. Questo è in realtà un esempio di modulo di aspetto che definisce i metodi da chiamare in vari punti.

package com.xx.yy;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;

@Aspect
public class Logging {

   /** Following is the definition for a pointcut to select
    *  all the methods available. So advice will be called
    *  for all the methods.
    */
   @Pointcut("execution(* com.xx.yy.*.*(..))")
   private void selectAll(){}

   /** 
    * This is the method which I would like to execute
    * before a selected method execution.
    */
   @Before("selectAll()")
   public void beforeAdvice(){
      System.out.println("Going to setup student profile.");
   }

   /** 
    * This is the method which I would like to execute
    * after a selected method execution.
    */
   @After("selectAll()")
   public void afterAdvice(){
      System.out.println("Student profile has been setup.");
   }

   /** 
    * This is the method which I would like to execute
    * when any method returns.
    */
   @AfterReturning(pointcut = "selectAll()", returning="retVal")
   public void afterReturningAdvice(Object retVal){
      System.out.println("Returning:" + retVal.toString() );
   }

   /**
    * This is the method which I would like to execute
    * if there is an exception raised by any method.
    */
   @AfterThrowing(pointcut = "selectAll()", throwing = "ex")
   public void AfterThrowingAdvice(IllegalArgumentException ex){
      System.out.println("There has been an exception: " + ex.toString());   
   }
   
}

Di seguito è riportato il contenuto del Student.java di file:

package com.xx.yy;

public class Student {
   private Integer age;
   private String name;

   public void setAge(Integer age) {
      this.age = age;
   }
   public Integer getAge() {
	  System.out.println("Age : " + age );
      return age;
   }

   public void setName(String name) {
      this.name = name;
   }
   public String getName() {
      System.out.println("Name : " + name );
      return name;
   }
   public void printThrowException(){
      System.out.println("Exception raised");
      throw new IllegalArgumentException();
   }
}

Di seguito è riportato il contenuto del MainApp.java di file:

package com.quickgo;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = 
             new ClassPathXmlApplicationContext("Beans.xml");

      Student student = (Student) context.getBean("student");

      student.getName();
      student.getAge();
      
      student.printThrowException();
   }
}

In seguito è il file di configurazione beans.xml :

<?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 ">

    <aop:aspectj-autoproxy/>

   <!-- Definition for student bean -->
   <bean id="student" class="com.quickgo.Student">
      <property name="name"  value="Zara" />
      <property name="age"  value="11"/>      
   </bean>

   <!-- Definition for logging aspect -->
   <bean id="logging" class="com.quickgo.Logging"/> 
      
</beans>

Una volta che hai finito con la creazione di file di origine e di configurazione dei bean, cerchiamo di eseguire l’applicazione. Se tutto va bene con l’applicazione, stamperà il seguente messaggio:

Going to setup student profile.
Name : Zara
Student profile has been setup.
Returning:Zara
Going to setup student profile.
Age : 11
Student profile has been setup.
Returning:11
Going to setup student profile.
Exception raised
Student profile has been setup.
There has been an exception: java.lang.IllegalArgumentException
.....
other exception content