Introduction aux types de conseils au printemps

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.

Advice est une action entreprise par un aspect à un point de jointure particulier. Les différents types de conseils incluent les conseils «autour», «avant» et «après». L'objectif principal de certains aspects est de prendre en charge des 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, consultezyesterdays intro to these.

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 de l'annotation@Aspect d'AspectJ.

@Configuration
@ComponentScan(basePackages = {"org.example.dao", "org.example.aop"})
@EnableAspectJAutoProxy
public class TestConfig {
    ...
}

3. Avant les conseils

Comme son nom l'indique, ce conseil est exécuté avant le point de jointure. Cela n'empêche pas la poursuite de l'exécution de la méthode conseillée à 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);
    }
}

L'avis delogMethodCall sera exécuté avant toute méthode de référentiel définie par le pointcut derepositoryMethods.

4. Après avis

Après un conseil, 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.

D'une certaine manière, il est similaire à un blocfinally. Dans le cas où vous avez besoin d'un conseil pour être déclenché seulement après une exécution normale, vous devez utiliser lesreturning advice déclarés 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 utiliserthrowing advice, déclaré en utilisant l'annotation@AfterThrowing.

Supposons que nous souhaitons notifier certains composants d'application lorsqu'une nouvelle instance deFoo est créée. Nous pourrions publier un événement à partir deFooDao, 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@AfterReturning, nous pouvons accéder à la valeur de retour de la méthode cible. Deuxièmement, en déclarant un paramètre de typeJoinPoint,, nous pouvons accéder aux arguments de l’invocation de la méthode cible.

Ensuite, nous créons un écouteur qui va simplement enregistrer l'événement. Vous pouvez en savoir plus sur les événements dansthis tutorial:

@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

Around advice entoure un point de jointure tel qu'un appel de méthode.

C'est le genre de conseil le plus puissant. Around advice peut appliquer un comportement personnalisé à la fois avant et après l’appel de la méthode. Il lui incombe également de choisir 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 vous souhaitiez mesurer le temps d'exécution de la méthode. Pour cela, vous pouvez créer l'aspect suivant:

@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 point de couperepositoryClassMethods est exécuté.

Ce conseil prend un paramètre de typeProceedingJointPoint. 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 estObject puisque la méthode cible peut renvoyer un résultat de n'importe quel type. Si la méthode cible estvoid,null sera renvoyé. 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. Vue d'ensemble

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 un schéma et en utilisant les annotations AspectJ. Nous avons également fourni plusieurs applications de conseil possibles.

L'implémentation de tous ces exemples et extraits de code se trouve dansmy github project - il s'agit d'un projet basé sur Eclipse, il devrait donc être facile à importer et à exécuter tel quel.