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

Ejemplo de anotación de Spring AOP AspectJ

Marco de trabajo SpringSe recomienda que utilices Spring 1.2Se utiliza en la implementación de AOP de estilo antiguo dtd Implementación de Spring AspectJ AOPFácil de usar.

Hay dos métodos para usar la implementación de Spring AOP AspectJ:

A través de las anotaciones: Vamos a aprenderlo aquí. A través de la configuración xml (basada en patrón): Vamos a aprenderlo en la próxima página.

Nota: Para entender el concepto de AOP y sus ventajas, por favor visite aquí. Tutorial de concepto de AOP

La implementación de Spring AspectJ AOP proporciona muchas anotaciones:

@Aspect Declarar esta clase como aspecto. @Pointcut Se declaró la expresión de punto de interrupción.

Las anotaciones utilizadas para crear sugerencias son las siguientes:

@Before Se declaró la sugerencia before. Se aplica antes de llamar al método real. @After Se declaró la sugerencia after. Se aplica después de llamar al método real y antes de devolver el resultado. @AfterReturning Se declaró la sugerencia de retorno después. Se aplica después de llamar al método real y antes de devolver el resultado. Pero puedes obtener el valor del resultado en la sugerencia. @Around Se declaró la sugerencia de entorno. Se aplica antes y después de llamar al método real. @AfterThrowing Se declaró la sugerencia throws. Si el método real lanza una excepción, se aplicará este método.

Entender la expresión de punto de interrupción

La expresión de punto de interrupción es un lenguaje de expresión de Spring AOP.

@Pointcut Los comentarios se utilizan para definir puntos de interrupción. También podemos referirnos a las expresiones de punto de interrupción mediante nombres. Veamos un ejemplo simple de expresión de punto de interrupción.

@Pointcut("execution(")* Operación.*(..))
private void doSomething() {}

El nombre de la expresión de punto de interrupción es doSomething(). Se aplicará a todos los métodos de la clase Operation, sin importar el tipo de retorno.

Entender la expresión de punto de interrupción

Vamos a intentar entender la expresión de punto de interrupción a través del siguiente ejemplo:

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

Se aplicará a todos los métodos públicos.


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

Se aplicará a todos los métodos públicos de la clase Operation.


@Pointcut("execution(")* Operación.*(..))

Se aplicará a todos los métodos de la clase Operation.


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

Se aplicará a todos los métodos públicos de la clase Employee.


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

Se aplicará a todos los métodos de la clase Operation que devuelvan int.


1Ejemplo de @Before

Aplicar el consejo Before de AspectJ antes de los métodos de lógica de negocio real. Puede ejecutar cualquier operación aquí, como la conversión, la autenticación, etc.

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

Archivo: Operation.java

package com.w;3codebox;
public class Operation{
	public void msg(){System.out.println("método msg llamado");}
	public int m(){System.out.println("método m llamado");return 2;}
	public int k(){System.out.println("método k llamado");return 3;}
}

Ahora, creamos la clase de aspecto que contiene el consejo antes.

Archivo: TrackOperation.java

package com.w;3codebox;
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(")* Operación.*(..))
	public void k(){}//nombre del punto de corte
	@Before("k()")//Aplicar el punto de interrupción en el aviso antes
	public void myadvice(JoinPoint jp)//es un consejo (antes del consejo)
	{
		System.out.println(" preocupación adicional");
		//System.out.println(" Firma del método: "}  + jp.getSignature());
	}
}

Ahora creamos el archivo applicationContext.xml que define el bean.

Archivo: 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>

Ahora, llamemos al método real.

Archivo: Test.java

package com.w;3codebox;
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("llamando msg...");
		e.msg();
		System.out.println("calling m...");
		e.m();
		System.out.println("calling k...");
		e.k();
	}
}

Salida

llamando a msg...
preocupación adicional
msg() method invoked
calling m...
preocupación adicional
m() method invoked
calling k...
preocupación adicional
k() method invoked

Como puedes ver, antes de llamar a los métodos msg(), m() y k(), también se muestran otros problemas.

Ahora, si cambias la expresión del punto de corte como se muestra a continuación:

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

Ahora, nos enfocaremos más en los métodos que comienzan con m en la clase Operation. La salida será como se muestra a continuación:

llamando a msg...
preocupación adicional
msg() method invoked
calling m...
preocupación adicional
m() method invoked
calling k...
k() method invoked

Ahora puedes ver que antes de llamar al método k() no se imprime otro problema.


2Ejemplo de @After

Después de llamar al método de lógica de negocio real, se aplica el AspectJ después del consejo de after. Se puede usar para mantener el registro, la seguridad, las notificaciones, etc.

Aquí, suponemos Operation.java , applicationContext.xml y Test.java 文件与@Before示例中给出的文件相同。

Archivo: TrackOperation.Java
package com.w;3codebox;
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(")* Operación.*(..))
	public void k(){}//nombre del punto de corte
	@After("k()")//aplicando el punto de corte en el consejo después
	public void myadvice(JoinPoint jp)//es un consejo (después del consejo)
	{
		System.out.println(" preocupación adicional");
		//System.out.println(" Firma del método: "}  + jp.getSignature());
	}
}
 

Salida

llamando a msg...
msg() method invoked
preocupación adicional
calling m...
m() method invoked
preocupación adicional
calling k...
k() method invoked
preocupación adicional
 

Puedes ver que después de llamar a los métodos msg(), m() y k(), también aparecen otros problemas.


3Ejemplo de @AfterReturning

Al usarlo después del consejo de retorno, podemos obtener el resultado en el consejo.

Crear la lógica de negocio que contiene lo siguiente.

Archivo: Operation.java

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

Crear la clase de aspecto que contiene el consejo de retorno.

Archivo: TrackOperation.java

package com.w;3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class TrackOperation{
	@AfterReturning(
		      pointcut = "execution(* Operación.*(..))",
		      returning = "result")
		      
	public void myadvice(JoinPoint jp, Object result)//es un consejo (después de devolver el consejo)
	{
		System.out.println(" preocupación adicional");
		System.out.println(" Firma del método: "}  + jp.getSignature());
		System.out.println("Result in advice: ")+result);
		System.out.println("end of after returning advice...");
	}
}
 

Archivo: applicationContext.xml

como se indica en el ejemplo de @Before.

Archivo: Test.java

Ahora creamos la clase Test que llama al método real.

package com.w;3codebox;
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());
	}
}
 

Salida

calling m...
m() method invoked
preocupación adicional
Method Signature: int com.w3codebox.Operation.m()
Result in advice: 2
end of after returning advice...
2
calling k...
k() method invoked
preocupación adicional
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示例中给出的文件相同。

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

Archivo: Operation.java

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

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

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

Archivo: TrackOperation.java

package com.w;3codebox;
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(")* Operación.*(..))
	public void abcPointcut(){}
	@Around("abcPointcut()")
	public Object myadvice(ProceedingJoinPoint pjp) throws Throwable 
	{
		System.out.println("Interés adicional antes de llamar al método real");
		Object obj=pjp.proceed();
		System.out.println("Interés adicional después de llamar al método real");
		return obj;
	}
}
 

Archivo: Test.java

Ahora creamos la clase Test que llama al método real.

package com.w;3codebox;
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();
	}
}
 

Salida

Interés adicional antes de llamar al método real
Se invoca msg()
Interés adicional después de llamar al método real
Interés adicional antes de llamar al método real
Se invoca display()
Interés adicional después de llamar al método real
 

Puedes ver que antes y después de llamar al método msg() y mostrar, también se imprimen otros problemas.


5Ejemplo de @AfterThrowing

Al usar la sugerencia after throw, podemos imprimir la excepción en la clase TrackOperation. Vamos a ver un ejemplo de la sugerencia AspectJ AfterThrowing.

Crear una clase que contenga lógica de negocio.

Archivo: Operation.java

package com.w;3codebox;
public class Operation{
	public void validate(int edad) throws Exception{
	if(edad<18){
		throw new ArithmeticException("Edad no válida");
	}
	else{
		System.out.println("Gracias por votar");
	}
	}
}
 

Crear una clase de aspecto que contiene la lógica después de lanzar el consejo.

Aquí, también necesitamos pasar una referencia a Throwable para poder interceptar la excepción aquí.

Archivo: TrackOperation.java

package com.w;3codebox;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class TrackOperation{
	@AfterThrowing(
		      pointcut = "execution(* Operación.*(..))",
		      throwing = "error")
		      
	public void myadvice(JoinPoint jp, Throwable error)//es un consejo
	{
		System.out.println(" preocupación adicional");
		System.out.println(" Firma del método: "}  + jp.getSignature());
		System.out.println("La excepción es: "}+error);
		System.out.println("final de after throwing advice...");
	}
}
 

Archivo: applicationContext.xml

como se indica en el ejemplo de @Before.

Archivo: Test.java

Ahora creamos la clase Test que llama al método real.

package com.w;3codebox;
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("llamando a validate...");
		try{
			op.validate(19);
		catch(Exception e){System.out.println(e);}
		System.out.println("llamando a validate nuevamente...");
		try{
		    op.validate(11);
		catch(Exception e){System.out.println(e);}
	}
}
 

Salida

llamando a validate...
Gracias por votar
llamando a validate nuevamente...
preocupación adicional
Firma del método: void com.w3codebox.Operation.validate(int)
La excepción es: java.lang.ArithmeticException: Edad no válida
final de después de lanzar el consejo...
java.lang.ArithmeticException: Edad no válida