Principes fondamantaux d'AOP
L'Aspect-Oriented Prorgamming (AOP) dans Spring permet d'intégrer des fonctionnalités transversales comme les logs, la sécurité ou les transactions sans modifier le code métier. Les concepts clés incluent :
- Aspect : Module encapsulant des préoccupations transversales
- Pointcut : Expression définissant les points d'exécution ciblés
- Advice : Bloc de code exécuté à des moments spécifiques
- JointPoint : Point d'exécution spécifique dans l'application
Implémetnation via interfaces Spring
Création d'un aspect utilisant l'interface AfterReturningAdvice :
public class PerformanceLogger implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) {
System.out.println("Méthode " + method.getName() +
" exécutée en " + (System.currentTimeMillis() - (Long)args[0]) + "ms");
}
}
Configuration XML avec pointcut réutilisable :
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop">
<bean id="service" class="com.example.BusinessService"/>
<bean id="perfLogger" class="com.example.PerformanceLogger"/>
<aop:config>
<aop:pointcut id="businessMethods"
expression="execution(* com.example.BusinessService.process*(..))"/>
<aop:advisor advice-ref="perfLogger" pointcut-ref="businessMethods"/>
</aop:config>
</beans>
Configuration par définition d'aspect
Classe d'aspect avec méthodes de log personnalisées :
public class SecurityAspect {
public void verifyAccess(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
if (!SecurityContext.hasPermission(methodName)) {
throw new AccessDeniedException("Accès refusé à " + methodName);
}
}
}
Configuration XML avancée :
<aop:config>
<aop:aspect id="securityAspect" ref="securityAspect">
<aop:pointcut id="secureMethods"
expression="execution(* com.example.SecureService.*(..))"/>
<aop:before method="verifyAccess" pointcut-ref="secureMethods"/>
</aop:aspect>
</aop:config>
Approche basée sur les annotations
Exemple d'aspect utilisant les annotations AspectJ :
@Aspect
public class DebugAspect {
@Before("execution(* com.example.DataService.retrieve*(..))")
public void logRequest(JoinPoint joinPoint) {
System.out.println("Requête reçue: " + joinPoint.getSignature());
}
@Around("execution(* com.example.DataService.*(..))")
public Object measureExecutionTime(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
Object result = pjp.proceed();
System.out.println(pjp.getSignature() + " exécuté en " +
(System.currentTimeMillis() - start) + "ms");
return result;
}
}
Configuration requise pour activer les aspects :
<bean class="com.example.DebugAspect"/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
Génération de proxies dans Spring
- JDK Dynamic Proxy : Utilisé par défaut pour les interfaces
- CGLIB : Activé avec
proxy-target-class="true", génère des sous-classes
Ordre d'exécution des conseils dans Spring 5 :
- @Around (avant)
- @Before
- Méthode cible
- @AfterReturning
- @After
- @Around (après)