Programmmation par aspect avec Spring AOP

Note
This article was last updated on 2023-03-02, the content may be out of date.

Une fois n’est pas coutume, voici un article qui reprend des basiques de la programmation. J’aborde une stack JAVA, mais c’est applicable à d’autres langages.

Il existe une fonctionnalité très intéressante dans Spring (et dans J(akarta)EE) que l’on oublie assez souvent : l’AOP ou encore la programmation par aspect. Cette manière de programmer permet notamment de séparer le code fonctionnel et technique.
Si vous faites du JAVA, vous utilisez déjà l’AOP. En effet, quand vous faites une insertion en base via JPA dans un EJB ou un bean annoté @Transactional, une transaction est initiée au début de la méthode et fermée à la fin.

Avec Spring et notamment dans Spring boot, voici comment initier l’AOP.

Ajouter le starter AOP:

1
2
3
4
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

Dans la configuration ci-dessous, je prendrai comme exemple le logging des méthodes ( un log en début de méthode et un log en fin ). 

La définition des aspects se fait dans des classes annotées par @Configuration.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Configuration
@Aspect
@ConditionalOnProperty(name = "debug.enabled", havingValue = "true")
public class DebuggingConfiguration {

private static final Logger LOGGER = LoggerFactory.getLogger(DebuggingConfiguration.class);
private static final String WITHIN_MY_PACKAGE = "within(my.package..*)";

/**
* Log before execution
*
* @param joinPoint the current method
*/
@Before(WITHIN_MY_PACKAGE)
public void logBeforeExecution(JoinPoint joinPoint) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Beginning of method : [{}]", joinPoint.getSignature().getName());
}
}

/**
* Log after execution
*
* @param joinPoint the current method
*/
@After(WITHIN_MY_PACKAGE)
public void logAfterExecution(JoinPoint joinPoint) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("End of method : [{}]", joinPoint.getSignature().getName());
}
}
}

L’utilisation de l’ annotation @ConditionalOnProperty me permet d’activer cette classe de configuration seulement si la propriété debug.enabled est initialisée à true.

Les annotations @Before et @After indiquent à Spring AOP quand exécuter ces méthodes ou sur quelles méthodes. Dans mon cas, quand les méthodes appelées sont définies dans les classes d’un package défini.

Pour plus de détails sur la syntaxe et les possibilités, vous pouvez vous référer à la documentation.