English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
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.
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.
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.
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.
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.
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示例中给出的文件相同。
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.
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类。
围绕通知的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.
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