Introduction aux types de conseils au printemps

1. Vue d'ensemble

Dans cet article, nous aborderons différents types de conseils AOP qui peuvent être créés au printemps.

Le conseil est une action prise par un aspect à un point de jonction particulier. Différents types de conseils comprennent les conseils «autour», «avant» et «après». L'objectif principal des aspects est de prendre en charge les problèmes transversaux, tels que la journalisation, le profilage, la mise en cache et la gestion des transactions.

Et si vous souhaitez approfondir les expressions ponctuelles, consultez la précédente introduction à celles-ci.

2. Conseils habilitants

Avec Spring, vous pouvez déclarer des conseils en utilisant les annotations AspectJ, mais vous devez d'abord appliquer l' annotation @EnableAspectJAutoProxy à votre classe de configuration , ce qui permettra la prise en charge de la gestion des composants marqués avec l' annotation @Aspect d'AspectJ .

@Configuration @EnableAspectJAutoProxy public class AopConfiguration { ... }

2.1. Botte de printemps

Dans les projets Spring Boot, nous n'avons pas à utiliser explicitement @EnableAspectJAutoProxy . Il existe une configuration AopAutoConfiguration dédiée qui active le support AOP de Spring si l' aspect ou le conseil est sur le chemin de classe .

3. Avant l'avis

Ce conseil, comme son nom l'indique, est exécuté avant le point de jointure. Il n'empêche pas l'exécution continue de la méthode qu'il conseille à moins qu'une exception ne soit levée.

Considérez l'aspect suivant qui enregistre simplement le nom de la méthode avant son appel:

@Component @Aspect public class LoggingAspect { private Logger logger = Logger.getLogger(LoggingAspect.class.getName()); @Pointcut("@target(org.springframework.stereotype.Repository)") public void repositoryMethods() {}; @Before("repositoryMethods()") public void logMethodCall(JoinPoint jp) { String methodName = jp.getSignature().getName(); logger.info("Before " + methodName); } }

Le conseil logMethodCall sera exécuté avant toute méthode de référentiel définie par le pointcut repositoryMethods .

4. Après avis

After Advice, déclaré à l'aide de l' annotation @After , est exécuté après l'exécution d'une méthode correspondante, qu'une exception ait été levée ou non.

À certains égards, c'est similaire à un bloc finally . Dans le cas où vous avez besoin que le conseil ne soit déclenché qu'après une exécution normale, vous devez utiliser l' avis de retour déclaré par l' annotation @AfterReturning . Si vous souhaitez que votre conseil ne soit déclenché que lorsque la méthode cible lève une exception, vous devez utiliser le conseil de lancement, déclaré à l'aide de l' annotation @AfterThrowing .

Supposons que nous souhaitons notifier certains composants de l'application lorsqu'une nouvelle instance de Foo est créée. Nous pourrions publier un événement de FooDao , mais cela violerait le principe de responsabilité unique.

Au lieu de cela, nous pouvons accomplir cela en définissant l'aspect suivant:

@Component @Aspect public class PublishingAspect { private ApplicationEventPublisher eventPublisher; @Autowired public void setEventPublisher(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } @Pointcut("@target(org.springframework.stereotype.Repository)") public void repositoryMethods() {} @Pointcut("execution(* *..create*(Long,..))") public void firstLongParamMethods() {} @Pointcut("repositoryMethods() && firstLongParamMethods()") public void entityCreationMethods() {} @AfterReturning(value = "entityCreationMethods()", returning = "entity") public void logMethodCall(JoinPoint jp, Object entity) throws Throwable { eventPublisher.publishEvent(new FooCreationEvent(entity)); } }

Notez tout d'abord qu'en utilisant l' annotation @AfterR eturning, nous pouvons accéder à la valeur de retour de la méthode cible. Deuxièmement, en déclarant un paramètre de type JoinPoint, nous pouvons accéder aux arguments de l'invocation de la méthode cible.

Ensuite, nous créons un écouteur qui enregistrera simplement l'événement:

@Component public class FooCreationEventListener implements ApplicationListener { private Logger logger = Logger.getLogger(getClass().getName()); @Override public void onApplicationEvent(FooCreationEvent event) { logger.info("Created foo instance: " + event.getSource().toString()); } }

5. Autour des conseils

Un conseil entoure un point de jointure tel qu'un appel de méthode.

C'est le type de conseil le plus puissant. Around Advice peut effectuer un comportement personnalisé avant et après l'appel de la méthode. Il est également responsable du choix de passer au point de jointure ou de raccourcir l'exécution de la méthode conseillée en fournissant sa propre valeur de retour ou en lançant une exception.

Pour démontrer son utilisation, supposons que nous souhaitons mesurer le temps d'exécution de la méthode. Créons un aspect pour cela:

@Aspect @Component public class PerformanceAspect { private Logger logger = Logger.getLogger(getClass().getName()); @Pointcut("within(@org.springframework.stereotype.Repository *)") public void repositoryClassMethods() {}; @Around("repositoryClassMethods()") public Object measureMethodExecutionTime(ProceedingJoinPoint pjp) throws Throwable { long start = System.nanoTime(); Object retval = pjp.proceed(); long end = System.nanoTime(); String methodName = pjp.getSignature().getName(); logger.info("Execution of " + methodName + " took " + TimeUnit.NANOSECONDS.toMillis(end - start) + " ms"); return retval; } }

Ce conseil est déclenché lorsque l'un des points de jointure correspondant au pointcut repositoryClassMethods est exécuté.

Ce conseil prend un paramètre de type ProceedingJointPoint . Le paramètre nous donne l'occasion d'agir avant l'appel de la méthode cible. Dans ce cas, nous enregistrons simplement l'heure de début de la méthode.

Deuxièmement, le type de retour de conseil est Object car la méthode cible peut renvoyer un résultat de n'importe quel type. Si la méthode cible est void, null sera retourné. Après l'appel de la méthode cible, nous pouvons mesurer le timing, le consigner et renvoyer la valeur de résultat de la méthode à l'appelant.

6. Aperçu

Dans cet article, nous avons appris les différents types de conseils de Spring et leurs déclarations et implémentations. Nous avons défini les aspects en utilisant une approche basée sur des schémas et en utilisant des annotations AspectJ. Nous avons également fourni plusieurs applications de conseil possibles.

L'implémentation de tous ces exemples et extraits de code peut être trouvée dans mon projet GitHub.