@ JEE Back-End - Aspect Oriented Programming

JEE Back-end

Spring Core : Aspect Oriented Programming

Aspect Oriented Programming (AOP)

L'AOP consiste à injecter du code avant, après ou autour des appels à certaines méthodes.

L'AOP est utilisé pour gérer des aspects transversaux de l'application: logging, caching, timing ...

Plusieurs frameworks permettent de faire de l'AOP: Spring AOP, AspectJ, ...

AOP en Spring

En Spring, cette injection de code se fait à runtime et uniquement sur des objets gérés par le conteneur IoC.

AspectJ réalise cette injection (aussi appelé tissage) au moment de la compilation. On peut configurer Spring réaliser le tissage en utilisant AspectJ mais nous allons utiliser Spring AOP ici.

Spring crée à l'exécution un proxy pour le bean dans lequel on veut injecter le code.

Proxy dynamique

Le code à injecter est fourni dans des classes marquées par l'annotation @Aspect.

A la création du bean, un proxy est crée automatiquement. Ce proxy se charge d'appeler les les aspects concernant cette méthode.

Comme les proxys sont fait dynamiquement, on a les limitations vu dans le cours de design patterns.

Injection @Before une méthode

@Aspect
@Component
public class MyAspect {

    @Before("execution(* fr.uge.jee.aop.Database.add*(..))")
    public void beforeAdd(JoinPoint jp) throws Throwable {
        System.out.println("This is printed before the method call")
    }
}

Le code de beforeAdd sera injecté avant l'appel à toute méthode d'un bean de type fr.uge.jee.aop.Database dont le nom commence par add.

L'objet JoinPoint représente le point d'injection. C'est à dire la méthode où le code va être injecter.

Injection @AfterReturning une méthode

@Aspect
@Component
public class MyAspect {

    @AfterReturning(value="execution(* fr.uge.jee.aop.Database.add*(..))",returning="returnValue")
    public void afterAdd(JoinPoint jp,Object returnValue) throws Throwable {
        System.out.println("This is printed after the method call with returned "+returnValue);
    }
}

On a accès à la valeur de retour de la méthode avec value.

Injection @Around une méthode

@Aspect
@Component
public class MyAspect {

    @Around(value="execution(* fr.uge.jee.aop.Database.add*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("This is printed before the method");
        var ret = pjp.proceed(); // call the method
        System.out.println("This is printed after the method");
        return ret;
    }
}

Le ProceedingJoinPoint représente l'appel qui va se faire à la méthode.

Configuration with Aspects

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class Config {
}