Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Spring AOP 2.x e supporto ad AspectJ

Definire gli aspect tramite annotation grazie al supporto ad AspectJ
Definire gli aspect tramite annotation grazie al supporto ad AspectJ
Link copiato negli appunti

A partire dalla versione 2.x Spring AOP ha subito notevoli cambiamenti rivolti a rendere più coerente l'implementazione dell'Aspect Oriented Programming nel framework. Pur mantenendo la compatibilità  con le API viste in precedenza, è stato introdotto un nuovo e più potente meccanismo
basato sull'introduzione del supporto ad AspectJ (uno dei più completi e diffusi framework AOP nel panorama Java) e sul concetto di Aspect.

Dal punto di vista pratico un Aspect è implementato attraverso un semplice POJO con l'ausilio delle annotation di AspectJ (@AspectJ). L'adozione di @AspectJ, grazie al suo crescente supporto, oltre a semplificare la scrittura degli Aspect ne favorisce la loro compatibilità verso framework AOP di terze parti.

Gli elementi fondamentali: Aspect, Advice e Pointcut

Riprendiamo ora l'esempio del logging visto in precedenza e cerchiamo di implementarlo in questa nuova ottica. Per prima cosa definiamo l'Aspect responsabile della funzionalità  di logging, creando la classe LogAspect e annotandola con l'apposita annotation @Aspect.

@Aspect
public class LogAspect {
       ...
}

Perchè l'Aspect sia completo occore definire gli Advice che dovranno essere eseguiti al verificarsi dei vari Join Point. In merito a questo punto occorre ricordare che anche se AspectJ è in grado di offrire un supporto completo a varie tipologie di Join Point, Spring AOP permette l'intercettazione esclusivamente dell'esecuzione dei metodi.

Per specificare un advice con @AspectJ basta semplicemente aggiungere alla classe rappresentante l'Aspect un metodo appositamente annotato. Volendo accedere alle informazioni specifiche del Join Point è possibile includere nella firma del metodo il parametro Join Point.

In Spring i tipi di annotation @AspectJ utilizzabili per gli Advice sono:

Advice Annotation Momento dell'esecuzione
@Before prima dell'esecuzione di un metodo.
@After dopo l'esecuzione di un metodo.
@AfterReturning dopo il ritorno di un risultato da parte di un metodo.
@AfterThrowing in seguito al rilancio di un eccezione da parte di un metodo.
@Around costruito intorno l'esecuzione di un metodo.

@Aspect
public class LogAspect {
	/*
	 * Applicato ad ogni metodo in seguito al rilancio di un eccezione
	 */
	@AfterThrowing("execution(* *.*(..))")
	public void afterThrowing(JoinPoint jp) throws Throwable {
		System.err.println("tErrore: " + jp.getSignature().getName());
	}
	/*
	 * Applicato prima dell'esecuzione dei metodi pubblici delle classi contenute
	 * nel package it.html.spring.book ed aventi nel nome la parola Dao
	 */
	@Before("execution(public * it.html.spring.book.*Dao.*(..))")
	public void beforeAdvice(JoinPoint jp) {
		// Log prima dell'invocazione del metodo
		System.out.println("[" + new Date() + "]nt"
				+  jp.getTarget().getClass() + "."  +  jp.getSignature().getName()
				+  "ntArgomenti: "+ Arrays.toString(jp.getArgs()));
	}
	/*
	 * Applicato dopo l'esecuzione dei metodi pubblici delle classi contenute
	 * in tutti i package della gerarchia it ed aventi nel nome la parola Dao
	 */
	@AfterReturning(
			pointcut = "execution(public * it..*Dao.*(..))",
			returning = "returnValue")
	public void afterReturning(JoinPoint jp, Object returnValue) throws Throwable {
		// Log del risultato dell'invocazione del metodo
		System.out.println("tRisultato: "+ returnValue);
	}	
}

Come possiamo notare dal codice, ogni Advice è corredato da un Pointcut (specificato come valore dell'annotation) che attraverso un predicato ne descrive i metodi per i quali deve essere eseguito.
Una descrizione dettagliata sui predicati esula dagli scopi di questa guida e può essere trovata qui. Per il momento ci basti dire che un predicato ha la seguente forma:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)

Tutti i parametri, ad eccezione di ret-type-pattern, name-pattern e param-pattern, sono opzionali.

Allo stesso modo è possibile dichiarare un around advice attraverso l'utilizzo dell'annotation @Around. Di seguito è mostrato un around advice applicato a tutti i metodi pubblici delle classi contenute nei package della gerarchia it.

/*
 * Applicato a tutti i metodi pubblici
 * delle classi contenute nei package della gerarchia it
 */	
@Around("execution(public * it..*(..))")
public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable {
	// Log prima dell'invocazione del metodo
	System.out.println("[" + new Date() + "]nt"
			+  pjp.getTarget().getClass() + "."  +  pjp.getSignature().getName()
			+  "ntArgomenti: "+ Arrays.toString(pjp.getArgs()));
	Object result = null;
	try
	{
		// Invocazione metodo
		result = pjp.proceed();
	}
	catch (Exception ex)
	{
		System.err.println("tErrore: " + pjp.getSignature().getName());
	}
	//Operazioni dopo l'esecuzione
	System.out.println("tRisultato: "+ result);
	return result;
}

Ti consigliamo anche