English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Esempio di annotazione AOP di Spring AOP

Framewrok SpringSi consiglia di utilizzare l'AOP basata su Spring 1.2 e vecchio stile dtd. Implementazione AOP di Spring AspectJFacile da usare.

Ci sono due modi per implementare Spring AOP AspectJ:

Tramite annotazioni: impareremo questo qui. Tramite configurazione XML (basata su schema): impareremo questo nella prossima pagina.

Attenzione: Per comprendere i concetti di AOP e i loro vantaggi, visita qui. Tutorial sui concetti di AOP

L'esecuzione di Spring AspectJ AOP fornisce molte annotazioni:

@Aspect Declara questa classe come aspetto. @Pointcut Declara l'espressione di punto di intersezione.

Le annotazioni utilizzate per creare il consiglio sono le seguenti:

@Before Declara il consiglio before. Viene applicato prima della chiamata al metodo effettivo. @After Declara il consiglio after. Viene applicato dopo la chiamata al metodo effettivo e prima di restituire il risultato. @AfterReturning Declara il consiglio di ritorno dopo. Viene applicato dopo la chiamata al metodo effettivo e prima di restituire il risultato. Ma puoi ottenere il valore del risultato nel consiglio. @Around Declara il consiglio di circonferenza. Viene applicato prima e dopo la chiamata al metodo effettivo. @AfterThrowing Ha dichiarato il consiglio throws. Se il metodo reale lancia un'eccezione, viene applicato questo metodo.

Comprendere il punto di interruzione

Il punto di interruzione è un linguaggio di espressione di Spring AOP.

@Pointcut >I commenti servono a definire l'espressione del punto di interruzione. Possiamo anche fare riferimento all'espressione del punto di interruzione tramite il nome. Ecco un esempio semplice di espressione del punto di interruzione.

@Pointcut("execution(* Operation.*(..))")
private void doSomething() {}

Il nome dell'espressione del punto di interruzione è doSomething(). Verrà applicato a tutti i metodi della classe Operation indipendentemente dal tipo di ritorno.

Comprendere l'espressione del punto di interruzione

Proviamo a comprendere l'espressione del punto di interruzione con l'esempio seguente:

@Pointcut("execution(public * *(..))")

verrà applicato a tutti i metodi pubblici.


@Pointcut("execution(public Operation.*(..))")

verrà applicato a tutti i metodi pubblici della classe Operation.


@Pointcut("execution(* Operation.*(..))")

verrà applicato a tutti i metodi della classe Operation.


@Pointcut("execution(public Employee.set*(..))")

verrà applicato a tutti i metodi pubblici di Employee.


@Pointcut("execution(int Operation.*(..))")

verrà applicato a tutti i metodi della classe Operation che restituiscono int.


1、@Before esempio

Applica il consiglio Before di AspectJ prima del metodo della logica aziendale reale. Puoi eseguire qualsiasi operazione qui, ad esempio conversione, autenticazione ecc.

创建一个包含实际业务逻辑的类。

File: Operation.java

package com.w3codebox;
public class Operation{
	public void msg(){System.out.println("msg method invoked");}
	public int m(){System.out.println("m method invoked");return 2;}
	public int k(){System.out.println("k method invoked");return 3;}
}

Ora, crea una classe di aspetto che contiene il consiglio prima.

File: TrackOperation.java

package com.w3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TrackOperation{
	@Pointcut("execution(* Operation.*(..))")
	public void k(){}//nome del pointcut
	@Before("k()")//applica il punto di interruzione su notifica prima
	public void myadvice(JoinPoint jp)//è un consiglio (consiglio prima)
	{
		System.out.println("preoccupazione aggiuntiva");
		//System.out.println("Firma del metodo: " + jp.getSignature());
	}
}

Ora creiamo il file applicationContext.xml che definisce il bean.

File: applicationContext.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.xsd 
	   http://www.springframework.org/schema/aop 
	   http://www.springframework.org/schema/aop/spring-aop.xsd">
	<bean id="opBean" class="com.w3codebox.Operation">	</bean>
	<bean id="trackMyBean" class="com.w3codebox.TrackOperation"></bean>
	<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"></bean>
</beans>

Ora, chiamiamo il metodo reale.

File: Test.java

package com.w3codebox;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
	public static void main(String[] args){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Operation e = (Operation) context.getBean("opBean");
		System.out.println("chiamando msg...");
		e.msg();
		System.out.println("calling m...");
		e.m();
		System.out.println("calling k...");
		e.k();
	}
}

output

chiamando msg...
preoccupazione aggiuntiva
chiamata al metodo msg...
calling m...
preoccupazione aggiuntiva
m() method invoked
calling k...
preoccupazione aggiuntiva
k() method invoked

Come potete vedere, prima di chiamare i metodi msg(), m() e k(), viene visualizzato anche altri problemi.

Ora, se modificate l'espressione del punto di interruzione come segue:

@Pointcut("execution(* Operation.m*(..))")

Ora, daremo maggiore attenzione ai metodi che iniziano con la lettera 'm' nella classe Operation. L'output sarà come segue:

chiamando msg...
preoccupazione aggiuntiva
chiamata al metodo msg...
calling m...
preoccupazione aggiuntiva
m() method invoked
calling k...
k() method invoked

Ora puoi vedere che prima di chiamare il metodo k() non vengono stampati altri problemi.


2. Esempio @After

Dopo aver chiamato il metodo della logica del business reale, viene applicato l'AspectJ after advice. Può essere utilizzato per mantenere i log, la sicurezza, le notifiche, ecc.

Qui, presupponiamo Operation.java , applicationContext.xml e Test.java 文件与@Before示例中给出的文件相同。

File: TrackOperation.Java
package com.w3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TrackOperation{
	@Pointcut("execution(* Operation.*(..))")
	public void k(){}//nome del pointcut
	@After("k()")//applicare il pointcut sull'advice after
	public void myadvice(JoinPoint jp)//è un advice (after advice)
	{
		System.out.println("preoccupazione aggiuntiva");
		//System.out.println("Firma del metodo: " + jp.getSignature());
	}
}
 

output

chiamando msg...
chiamata al metodo msg...
preoccupazione aggiuntiva
calling m...
m() method invoked
preoccupazione aggiuntiva
calling k...
k() method invoked
preoccupazione aggiuntiva
 

Puoi vedere che dopo aver chiamato i metodi msg(), m() e k(), ci sono altri problemi.


3. Esempio @AfterReturning

Utilizzando l'advice dopo il ritorno, possiamo ottenere il risultato nel consiglio.

Creare la logica del business che contiene il seguente contenuto.

File: Operation.java

package com.w3codebox;
public class Operation{
	public int m(){System.out.println("chiamata al metodo m()");return 2;}
	public int k(){System.out.println("chiamata al metodo k()");return 3;}
}
 

Creare la classe del lato che contiene il consiglio di ritorno.

File: TrackOperation.java

package com.w3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class TrackOperation{
	@AfterReturning(
		      pointcut = "execution(* Operation.*(..))",
		      returning = "result")
		      
	public void myadvice(JoinPoint jp, Object result)//è un advice (after returning advice)
	{
		System.out.println("preoccupazione aggiuntiva");
		System.out.println("Firma del metodo: " + jp.getSignature());
		System.out.println("Risultato nell'advice: " + result);
		System.out.println("fine dell'after returning advice...");
	}
}
 

File: applicationContext.xml

come indicato nell'esempio @Before

File: Test.java

Ora creiamo la classe Test per chiamare il metodo reale.

package com.w3codebox;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
	public static void main(String[] args){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Operation e = (Operation) context.getBean("opBean");
		System.out.println("calling m...");
		System.out.println(e.m());
		System.out.println("calling k...");
		System.out.println(e.k());
	}
}
 

output

calling m...
m() method invoked
preoccupazione aggiuntiva
Method Signature: int com.w3codebox.Operation.m()
Result in advice: 2
end of after returning advice...
2
calling k...
k() method invoked
preoccupazione aggiuntiva
Method Signature: int com.w3codebox.Operation.k()
Result in advice: 3
end of after returning advice...
3
 

您可以看到返回值已打印两次,一次是由TrackOperation类打印,第二次是Test类。


4、@Around示例

围绕通知的AspectJ在调用实际的业务逻辑方法之前和之后都得到应用。

在这里,我们是假设   applicationContext.xml 文件与@Before示例中给出的文件相同。

创建一个包含实际业务逻辑的类。

File: Operation.java

package com.w3codebox;
public class Operation{
	public void msg(){System.out.println("msg() is invoked");}
	public void display(){System.out.println("display() is invoked");}
}
 

创建包含围绕建议的方面类。

您需要在advice方法中传递   PreceedingJoinPoint 引用,以便我们可以通过调用proce来进行请求()方法。

File: TrackOperation.java

package com.w3codebox;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class TrackOperation
{
	@Pointcut("execution(* Operation.*(..))")
	public void abcPointcut(){}
	@Around("abcPointcut()")
	public Object myadvice(ProceedingJoinPoint pjp) throws Throwable 
	{
		System.out.println("Preoccupazione aggiuntiva prima della chiamata al metodo reale");
		Object obj=pjp.proceed();
		System.out.println("Preoccupazione aggiuntiva dopo la chiamata al metodo reale");
		return obj;
	}
}
 

File: Test.java

Ora creiamo la classe Test per chiamare il metodo reale.

package com.w3codebox;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
	public static void main(String[] args){
		ApplicationContext context = new classPathXmlApplicationContext("applicationContext.xml");
		Operation op = (Operation) context.getBean("opBean");
		op.msg();
		op.display();
	}
}
 

output

Preoccupazione aggiuntiva prima della chiamata al metodo reale
msg() è chiamato
Preoccupazione aggiuntiva dopo la chiamata al metodo reale
Preoccupazione aggiuntiva prima della chiamata al metodo reale
display() è chiamato
Preoccupazione aggiuntiva dopo la chiamata al metodo reale
 

Vedi che prima e dopo la chiamata al metodo msg() e alla visualizzazione, vengono stampate altre domande.


5. Esempio @AfterThrowing

Utilizzando il suggerimento after throw, possiamo stampare l'eccezione nella classe TrackOperation. Vediamo un esempio di suggerimento AspectJ AfterThrowing.

Creare una classe che contiene la logica del business.

File: Operation.java

package com.w3codebox;
public class Operation{
	public void validate(int age) throws Exception{
	if(age<18){
		throw new ArithmeticException("Non è un'età valida");
	}
	else{
		System.out.println("Grazie per il voto");
	}
	}
}
 

Creare una classe di aspect che contiene l'advice lanciato dopo l'eccezione.

Qui dobbiamo passare anche un riferimento a Throwable, in modo che possiamo intercettare l'eccezione qui.

File: TrackOperation.java

package com.w3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class TrackOperation{
	@AfterThrowing(
		      pointcut = "execution(* Operation.*(..))",
		      throwing = "error")
		      
	public void myadvice(JoinPoint jp, Throwable error)//è un advice
	{
		System.out.println("preoccupazione aggiuntiva");
		System.out.println("Firma del metodo: " + jp.getSignature());
		System.out.println("Eccezione è: " + error);
		System.out.println("fine dell'advice lanciato...");
	}
}
 

File: applicationContext.xml

come indicato nell'esempio @Before

File: Test.java

Ora creiamo la classe Test per chiamare il metodo reale.

package com.w3codebox;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test{
	public static void main(String[] args){
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Operation op = (Operation) context.getBean("opBean");
		System.out.println("richiamo validate...");
		try{
			op.validate(19);
		catch(Exception e){System.out.println(e);}
		System.out.println("richiamo validate di nuovo...");
		try{
		    op.validate(11);
		catch(Exception e){System.out.println(e);}
	}
}
 

output

richiamo validate...
grazie per il voto
richiamo validate di nuovo...
preoccupazione aggiuntiva
firma metodo: void com.w3codebox.Operation.validate(int)
eccezione è: java.lang.ArithmeticException: età non valida
fine after throwing advice...
java.lang.ArithmeticException: età non valida