Le framework Spring est développé sur deux concepts clés – L’injection de dépendance et la programmation orientée aspect (Spring AOP).
Spring AOP
Nous avons déjà vu comment l’injection de dépendance de Spring fonctionne, aujourd’hui nous examinerons les concepts clés de la programmation orientée aspect et comment nous pouvons l’implémenter en utilisant le framework Spring.
Aperçu de Spring AOP
La plupart des applications d’entreprise ont des préoccupations transversales communes qui s’appliquent à différents types d’objets et de modules. Certaines des préoccupations transversales communes sont la journalisation, la gestion des transactions, la validation des données, etc. En programmation orientée objet, la modularité de l’application est réalisée par des classes, tandis qu’en programmation orientée aspect, la modularité de l’application est réalisée par des aspects et ils sont configurés pour traverser différentes classes. Spring AOP supprime la dépendance directe des tâches transversales des classes que nous ne pouvons pas réaliser grâce au modèle de programmation orientée objet normal. Par exemple, nous pouvons avoir une classe séparée pour la journalisation, mais encore une fois, les classes fonctionnelles devront appeler ces méthodes pour réaliser la journalisation dans toute l’application.
Concepts de base de la programmation orientée aspect
Avant de plonger dans la mise en œuvre de Spring AOP, nous devons comprendre les concepts de base de l’AOP.
- Aspect : Un aspect est une classe qui implémente des préoccupations propres à l’application d’entreprise qui traversent plusieurs classes, telles que la gestion des transactions. Les aspects peuvent être une classe normale configurée via la configuration XML de Spring ou nous pouvons utiliser l’intégration Spring AspectJ pour définir une classe comme aspect en utilisant l’annotation
@Aspect
. - Point de jonction: Un point de jonction est un point spécifique dans l’application tel que l’exécution d’une méthode, la gestion des exceptions, le changement de valeurs de variables d’objet, etc. En AOP Spring, un point de jonction est toujours l’exécution d’une méthode.
- Conseil: Les conseils sont des actions prises pour un point de jonction particulier. En termes de programmation, ce sont des méthodes qui sont exécutées lorsque certains points de jonction avec un point de coupe correspondant sont atteints dans l’application. Vous pouvez penser aux conseils comme des intercepteurs Struts2 ou des filtres Servlet.
- Point de coupe: Le point de coupe est une expression qui est associée à des points de jonction pour déterminer si le conseil doit être exécuté ou non. Le point de coupe utilise différents types d’expressions qui sont associées aux points de jonction et le framework Spring utilise le langage d’expression de point de coupe AspectJ.
- Objet cible: Ce sont les objets sur lesquels les conseils sont appliqués. L’AOP Spring est implémentée à l’aide de proxys d’exécution, donc cet objet est toujours un objet proxifié. Cela signifie qu’une sous-classe est créée à l’exécution où la méthode cible est remplacée et les conseils sont inclus en fonction de leur configuration.
- Proxy AOP: L’implémentation de Spring AOP utilise le proxy dynamique JDK pour créer des classes Proxy avec des classes cibles et des appels d’avis, appelées classes de proxy AOP. Nous pouvons également utiliser le proxy CGLIB en l’ajoutant en tant que dépendance dans le projet Spring AOP.
- Tissage: Il s’agit du processus de liaison des aspects avec d’autres objets pour créer des objets de proxy avisés. Cela peut être fait au moment de la compilation, au moment du chargement ou à l’exécution. Spring AOP effectue le tissage à l’exécution.
Types d’avis AOP
En fonction de la stratégie d’exécution de l’avis, ils se présentent sous les types suivants.
- Avis Avant: Ces avis s’exécutent avant l’exécution des méthodes du point de jonction. Nous pouvons utiliser l’annotation
@Before
pour marquer un type d’avis comme avis avant. - Avis Après (enfin): Un avis qui s’exécute après que la méthode du point de jonction a fini de s’exécuter, que ce soit normalement ou en lançant une exception. Nous pouvons créer un avis après en utilisant l’annotation
@After
. - Avis Après Retour: Parfois, nous voulons que les méthodes d’avis s’exécutent uniquement si la méthode du point de jonction s’exécute normalement. Nous pouvons utiliser l’annotation
@AfterReturning
pour marquer une méthode comme avis après retour. - Après le lancer de l’avis: Cet avis s’exécute uniquement lorsque la méthode du point de jonction lance une exception, nous pouvons l’utiliser pour annuler la transaction de manière déclarative. Nous utilisons l’annotation
@AfterThrowing
pour ce type d’avis. - Avis autour: C’est l’avis le plus important et puissant. Cet avis entoure la méthode du point de jonction et nous pouvons également choisir d’exécuter ou non la méthode du point de jonction. Nous pouvons écrire du code d’avis qui s’exécute avant et après l’exécution de la méthode du point de jonction. Il incombe à l’avis autour d’inviter la méthode du point de jonction et de renvoyer des valeurs si la méthode renvoie quelque chose. Nous utilisons l’annotation
@Around
pour créer des méthodes d’avis autour.
Les points mentionnés ci-dessus peuvent sembler confus, mais lorsque nous examinerons la mise en œuvre de Spring AOP, les choses seront plus claires. Commençons par créer un projet Spring simple avec des implémentations AOP. Spring prend en charge l’utilisation des annotations AspectJ pour créer des aspects et nous utiliserons cela pour simplifier. Toutes les annotations AOP mentionnées ci-dessus sont définies dans le package org.aspectj.lang.annotation
. Spring Tool Suite fournit des informations utiles sur les aspects, je vous suggère donc de l’utiliser. Si vous n’êtes pas familier avec STS, je vous recommanderais de jeter un coup d’œil au Tutoriel Spring MVC où j’ai expliqué comment l’utiliser.
Exemple de Spring AOP
Créez un nouveau projet Maven Spring Simple de sorte que toutes les bibliothèques Spring Core soient incluses dans les fichiers pom.xml et que nous n’ayons pas besoin de les inclure explicitement. Notre projet final ressemblera à l’image ci-dessous, nous examinerons en détail les composants principaux de Spring et les implémentations d’Aspects.
Dependencies Spring AOP AspectJ
Le framework Spring fournit un support AOP par défaut, mais comme nous utilisons des annotations AspectJ pour configurer les aspects et les conseils, nous devrions les inclure dans le fichier pom.xml.
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples</groupId>
<artifactId>SpringAOPExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<!-- Generic properties -->
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Spring -->
<spring-framework.version>4.0.2.RELEASE</spring-framework.version>
<!-- Logging -->
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
<!-- Test -->
<junit.version>4.11</junit.version>
<!-- AspectJ -->
<aspectj.version>1.7.4</aspectj.version>
</properties>
<dependencies>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
<!-- AspectJ dependencies -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</project>
Remarquez que j’ai ajouté les dépendances aspectjrt
et aspectjtools
(version 1.7.4) dans le projet. J’ai également mis à jour la version du framework Spring pour qu’elle soit la dernière à ce jour, c’est-à-dire 4.0.2.RELEASE.
Classe de modèle
Créons un simple bean Java que nous utiliserons pour notre exemple avec quelques méthodes supplémentaires. Code Employee.java :
package com.journaldev.spring.model;
import com.journaldev.spring.aspect.Loggable;
public class Employee {
private String name;
public String getName() {
return name;
}
@Loggable
public void setName(String nm) {
this.name=nm;
}
public void throwException(){
throw new RuntimeException("Dummy Exception");
}
}
Avez-vous remarqué que la méthode setName() est annotée avec l’annotation Loggable
. Il s’agit d’une annotation Java personnalisée définie par nous dans le projet. Nous examinerons son utilisation plus tard.
Classe de service
Créons une classe de service pour travailler avec le bean Employee. Code EmployeeService.java:
package com.journaldev.spring.service;
import com.journaldev.spring.model.Employee;
public class EmployeeService {
private Employee employee;
public Employee getEmployee(){
return this.employee;
}
public void setEmployee(Employee e){
this.employee=e;
}
}
I could have used Spring annotations to configure it as a Spring Component, but we will use XML based configuration in this project. EmployeeService class is very standard and just provides us an access point for Employee beans.
Configuration du bean Spring avec AOP
Si vous utilisez STS, vous avez la possibilité de créer un « Fichier de configuration de bean Spring » et de choisir l’espace de noms du schéma AOP, mais si vous utilisez un autre IDE, vous pouvez simplement l’ajouter dans le fichier de configuration de bean Spring. Mon fichier de configuration de bean de projet ressemble à ceci. spring.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="https://www.springframework.org/schema/aop"
xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-4.0.xsd
https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!-- Enable AspectJ style of Spring AOP -->
<aop:aspectj-autoproxy />
<!-- Configure Employee Bean and initialize it -->
<bean name="employee" class="com.journaldev.spring.model.Employee">
<property name="name" value="Dummy Name"></property>
</bean>
<!-- Configure EmployeeService bean -->
<bean name="employeeService" class="com.journaldev.spring.service.EmployeeService">
<property name="employee" ref="employee"></property>
</bean>
<!-- Configure Aspect Beans, without this Aspects advices wont execute -->
<bean name="employeeAspect" class="com.journaldev.spring.aspect.EmployeeAspect" />
<bean name="employeeAspectPointcut" class="com.journaldev.spring.aspect.EmployeeAspectPointcut" />
<bean name="employeeAspectJoinPoint" class="com.journaldev.spring.aspect.EmployeeAspectJoinPoint" />
<bean name="employeeAfterAspect" class="com.journaldev.spring.aspect.EmployeeAfterAspect" />
<bean name="employeeAroundAspect" class="com.journaldev.spring.aspect.EmployeeAroundAspect" />
<bean name="employeeAnnotationAspect" class="com.journaldev.spring.aspect.EmployeeAnnotationAspect" />
</beans>
Pour utiliser AOP Spring dans les beans Spring, nous devons faire ce qui suit:
- Déclarez l’espace de noms AOP avec xmlns:aop=“https://www.springframework.org/schema/aop”
- Ajoutez l’élément aop:aspectj-autoproxy pour activer la prise en charge de Spring AspectJ avec un proxy automatique à l’exécution
- Configurez les classes Aspect comme d’autres beans Spring
Vous pouvez voir que j’ai beaucoup d’aspects définis dans le fichier de configuration des beans de printemps, il est temps de les examiner un par un.
Exemple d’Aspect Before de Spring AOP
Code EmployeeAspect.java:
package com.journaldev.spring.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class EmployeeAspect {
@Before("execution(public String getName())")
public void getNameAdvice(){
System.out.println("Executing Advice on getName()");
}
@Before("execution(* com.journaldev.spring.service.*.get*())")
public void getAllAdvice(){
System.out.println("Service method getter called");
}
}
Les points importants dans la classe d’aspect ci-dessus sont:
- Les classes d’aspect doivent avoir l’annotation
@Aspect
. - L’annotation @Before est utilisée pour créer un conseil Before
- Le paramètre de chaîne passé dans l’annotation
@Before
est l’expression Pointcut - L’avis getNameAdvice() s’exécutera pour n’importe quelle méthode de bean Spring avec la signature
public String getName()
. C’est un point très important à retenir, si nous créons le bean Employee en utilisant l’opérateur new, les conseils ne seront pas appliqués. Seulement lorsque nous utiliserons ApplicationContext pour obtenir le bean, les conseils seront appliqués. - Nous pouvons utiliser l’astérisque (*) comme joker dans les expressions Pointcut, getAllAdvice() sera appliqué à toutes les classes du package
com.journaldev.spring.service
dont le nom commence parget
et ne prend pas d’arguments.
Nous examinerons l’avis en action dans une classe de test après avoir examiné tous les différents types de conseils.
Les méthodes de point de coupure Spring AOP et la réutilisation
Parfois, nous devons utiliser la même expression de point de coupure à plusieurs endroits, nous pouvons créer une méthode vide avec l’annotation @Pointcut
et ensuite l’utiliser comme expression dans les conseils. Code EmployeeAspectPointcut.java:
package com.journaldev.spring.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class EmployeeAspectPointcut {
@Before("getNamePointcut()")
public void loggingAdvice(){
System.out.println("Executing loggingAdvice on getName()");
}
@Before("getNamePointcut()")
public void secondAdvice(){
System.out.println("Executing secondAdvice on getName()");
}
@Pointcut("execution(public String getName())")
public void getNamePointcut(){}
@Before("allMethodsPointcut()")
public void allServiceMethodsAdvice(){
System.out.println("Before executing service method");
}
//Pointcut à exécuter sur toutes les méthodes des classes dans un package
@Pointcut("within(com.journaldev.spring.service.*)")
public void allMethodsPointcut(){}
}
L’exemple ci-dessus est très clair, plutôt qu’une expression, nous utilisons le nom de la méthode dans l’argument d’annotation de conseil.
Spring AOP JoinPoint et arguments de conseil
Nous pouvons utiliser JoinPoint comme paramètre dans les méthodes de conseil et l’utiliser pour obtenir la signature de la méthode ou l’objet cible. Nous pouvons utiliser l’expression args()
dans le point de coupure à appliquer à toute méthode qui correspond au motif d’argument. Si nous utilisons cela, alors nous devons utiliser le même nom dans la méthode de conseil d’où le type d’argument est déterminé. Nous pouvons également utiliser des objets génériques dans les arguments de conseil. Code EmployeeAspectJoinPoint.java:
package com.journaldev.spring.aspect;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class EmployeeAspectJoinPoint {
@Before("execution(public void com.journaldev.spring.model..set*(*))")
public void loggingAdvice(JoinPoint joinPoint){
System.out.println("Before running loggingAdvice on method="+joinPoint.toString());
System.out.println("Agruments Passed=" + Arrays.toString(joinPoint.getArgs()));
}
//Arguments de conseil, seront appliqués aux méthodes de bean avec un seul argument de type String
@Before("args(name)")
public void logStringArguments(String name){
System.out.println("String argument passed="+name);
}
}
Exemple de conseil After de Spring AOP
Jetons un coup d’œil à une classe d’aspect simple avec un exemple de conseil After, After Throwing et After Returning. Code EmployeeAfterAspect.java:
package com.journaldev.spring.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class EmployeeAfterAspect {
@After("args(name)")
public void logStringArguments(String name){
System.out.println("Running After Advice. String argument passed="+name);
}
@AfterThrowing("within(com.journaldev.spring.model.Employee)")
public void logExceptions(JoinPoint joinPoint){
System.out.println("Exception thrown in Employee Method="+joinPoint.toString());
}
@AfterReturning(pointcut="execution(* getName())", returning="returnString")
public void getNameReturningAdvice(String returnString){
System.out.println("getNameReturningAdvice executed. Returned String="+returnString);
}
}
Nous pouvons utiliser within
dans l’expression pointcut pour appliquer le conseil à toutes les méthodes de la classe. Nous pouvons utiliser le conseil @AfterReturning pour obtenir l’objet retourné par la méthode conseillée. Nous avons la méthode throwException() dans le bean Employee pour illustrer l’utilisation du conseil After Throwing.
Exemple d’aspect Around de Spring AOP
Comme expliqué précédemment, nous pouvons utiliser l’aspect Around pour couper l’exécution de la méthode avant et après. Nous pouvons l’utiliser pour contrôler si la méthode conseillée s’exécutera ou non. Nous pouvons également inspecter la valeur retournée et la modifier. Il s’agit du conseil le plus puissant et doit être appliqué correctement. Code EmployeeAroundAspect.java:
package com.journaldev.spring.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class EmployeeAroundAspect {
@Around("execution(* com.journaldev.spring.model.Employee.getName())")
public Object employeeAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("Before invoking getName() method");
Object value = null;
try {
value = proceedingJoinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("After invoking getName() method. Return value="+value);
return value;
}
}
Autour des conseils sont toujours nécessaires d’avoir ProceedingJoinPoint comme argument et nous devrions utiliser sa méthode proceed() pour invoquer la méthode objet ciblée conseillée. Si la méthode conseillée renvoie quelque chose, il revient à la responsabilité du conseil de le renvoyer au programme appelant. Pour les méthodes void, la méthode de conseil peut renvoyer null. Étant donné que le conseil autour coupe autour de la méthode conseillée, nous pouvons contrôler l’entrée et la sortie de la méthode ainsi que son comportement d’exécution.
Conseil Spring avec Pointcut Annotation Personnalisé
Si vous regardez toutes les expressions de point de coupe susmentionnées, il y a des chances qu’elles soient appliquées à d’autres beans où elles ne sont pas destinées. Par exemple, quelqu’un peut définir un nouveau bean Spring avec une méthode getName() et l’avis commencera à s’appliquer même si ce n’était pas prévu. C’est pourquoi nous devrions garder la portée de l’expression de point de coupe aussi étroite que possible. Une approche alternative consiste à créer une annotation personnalisée et à annoter les méthodes où nous voulons que l’avis soit appliqué. C’est le but d’avoir la méthode Employee setName() annotée avec l’annotation @Loggable. L’annotation @Transactional du framework Spring est un excellent exemple de cette approche pour la gestion des transactions Spring . Code Loggable.java:
package com.journaldev.spring.aspect;
public @interface Loggable {
}
Code EmployeeAnnotationAspect.java:
package com.journaldev.spring.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class EmployeeAnnotationAspect {
@Before("@annotation(com.journaldev.spring.aspect.Loggable)")
public void myAdvice(){
System.out.println("Executing myAdvice!!");
}
}
La méthode myAdvice() conseillera uniquement la méthode setName(). Il s’agit d’une approche très sûre et chaque fois que nous voulons appliquer l’avis sur une méthode, il suffit de l’annoter avec l’annotation Loggable.
Configuration XML de Spring AOP
I always prefer annotation but we also have the option to configure aspects in the spring configuration file. For example, let’s say we have a class as below. EmployeeXMLConfigAspect.java code:
package com.journaldev.spring.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
public class EmployeeXMLConfigAspect {
public Object employeeAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("EmployeeXMLConfigAspect:: Before invoking getName() method");
Object value = null;
try {
value = proceedingJoinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("EmployeeXMLConfigAspect:: After invoking getName() method. Return value="+value);
return value;
}
}
Nous pouvons le configurer en incluant la configuration suivante dans le fichier de configuration du bean Spring.
<bean name="employeeXMLConfigAspect" class="com.journaldev.spring.aspect.EmployeeXMLConfigAspect" />
<!-- Spring AOP XML Configuration -->
<aop:config>
<aop:aspect ref="employeeXMLConfigAspect" id="employeeXMLConfigAspectID" order="1">
<aop:pointcut expression="execution(* com.journaldev.spring.model.Employee.getName())" id="getNamePointcut"/>
<aop:around method="employeeAroundAdvice" pointcut-ref="getNamePointcut" arg-names="proceedingJoinPoint"/>
</aop:aspect>
</aop:config>
Les éléments de configuration AOP xml tirent leur clarté de leur nom, donc je n’entrerai pas dans les détails.
Exemple Spring AOP
Prenons un programme Spring simple et voyons comment tous ces aspects traversent les méthodes du bean. Code SpringMain.java :
package com.journaldev.spring.main;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.journaldev.spring.service.EmployeeService;
public class SpringMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml");
EmployeeService employeeService = ctx.getBean("employeeService", EmployeeService.class);
System.out.println(employeeService.getEmployee().getName());
employeeService.getEmployee().setName("Pankaj");
employeeService.getEmployee().throwException();
ctx.close();
}
}
Maintenant, lorsque nous exécutons le programme ci-dessus, nous obtenons la sortie suivante.
Mar 20, 2014 8:50:09 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@4b9af9a9: startup date [Thu Mar 20 20:50:09 PDT 2014]; root of context hierarchy
Mar 20, 2014 8:50:09 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring.xml]
Service method getter called
Before executing service method
EmployeeXMLConfigAspect:: Before invoking getName() method
Executing Advice on getName()
Executing loggingAdvice on getName()
Executing secondAdvice on getName()
Before invoking getName() method
After invoking getName() method. Return value=Dummy Name
getNameReturningAdvice executed. Returned String=Dummy Name
EmployeeXMLConfigAspect:: After invoking getName() method. Return value=Dummy Name
Dummy Name
Service method getter called
Before executing service method
String argument passed=Pankaj
Before running loggingAdvice on method=execution(void com.journaldev.spring.model.Employee.setName(String))
Agruments Passed=[Pankaj]
Executing myAdvice!!
Running After Advice. String argument passed=Pankaj
Service method getter called
Before executing service method
Exception thrown in Employee Method=execution(void com.journaldev.spring.model.Employee.throwException())
Exception in thread "main" java.lang.RuntimeException: Dummy Exception
at com.journaldev.spring.model.Employee.throwException(Employee.java:19)
at com.journaldev.spring.model.Employee$$FastClassBySpringCGLIB$$da2dc051.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:711)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
at com.journaldev.spring.model.Employee$$EnhancerBySpringCGLIB$$3f881964.throwException(<generated>)
at com.journaldev.spring.main.SpringMain.main(SpringMain.java:17)
Vous pouvez voir que les conseils s’exécutent un par un en fonction de leurs configurations de point de coupe. Vous devriez les configurer un par un pour éviter la confusion. C’est tout pour le Tutoriel Exemple Spring AOP. J’espère que vous avez appris les bases de l’AOP avec Spring et que vous pourrez en apprendre davantage à partir d’exemples. Téléchargez le projet d’exemple à partir du lien ci-dessous et jouez avec.