Faites du profilage avec Spring AOP

On peut trouver beaucoup de tutoriaux sur spring AOP avec l’exemple de logger.
Mais, quelque part, cet exemple est un peu déroutant pour les nouveaux arrivants. Alors, je vais vous présenter ici un exemple qui explique comment utiliser Spring AOP pour le profilage de temps d’exécution d’une fonction. L’exemple servira aussi pour connaitre simplement le temps d’exécution de certaines de vos fonctions si vous n’avez pas accès à JProfiler ou autres outils de profilage. Si vous voulez connaitre les principes fondamentaux de l’AOP je vous invite à lire l’article : “AOP Concepts et implémentations

Utilisation de spring AOP pour profiler le temps d’exécution d’une fonction

L’exemple est très simple, notre application a une interface métier avec son implémentation. Nous allons profiler le temps d’exécution d’une méthode.
Le profilage (profiling) est un bon exemple pour les préoccupations transversales de l’application.
L’utilisation de spring AOP est un bon choix pour l’implémenter. On verra par la suite étape par étape l’implémentation de notre exemple.

Environnement et structure de projet

Lancez votre IDE préféré IDE (j’utilise Eclipse Helios) et créez un nouveau projet Java avec la structure comme indiqué ci-dessous.

Nous allons avoir besoin de quelques librairies supplémentaires (Spring, Commons-logging, aspectjrt, aspectjweaver)  pour notre projet. Pour cela, nous allons utiliser Maven pour la gestion de dépendances. Votre fichier pom doit ressembler à celui-ci :


<project xmlns="http://maven.apache.org/POM/4.0.0" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>fr.soat.sprofiler</groupId>
   <artifactId>profilage-avec-spring-aop</artifactId>
   <version>1.0.0-SNAPSHOT</version>
   <name>profilage-avec-spring-aop</name>
   <description>Faites du profilage avec Spring AOP</description>

   <properties>
      <org.springframework.version>2.0.5</org.springframework.version>
   </properties>
   <build>
      <plugins>
         <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
               <source>1.5</source>
               <target>1.5</target>
            </configuration>
         </plugin>
      </plugins>
   </build>

   <dependencies>

      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring</artifactId>
         <version>${org.springframework.version}</version>
      </dependency>
      <dependency>
         <groupId>commons-logging</groupId>
         <artifactId>commons-logging</artifactId>
         <version>1.1.1</version>
      </dependency>
      <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjrt</artifactId>
         <version>1.6.12</version>
      </dependency>
      <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.6.12</version>
      </dependency>
      <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.9</version>
      </dependency>
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.8.1</version>
          <scope>test</scope>
      </dependency>

   </dependencies>
</project>

Vous pouvez télécharger les sources de projet ici.

La Logique métier

Nous allons commencer par écrire notre logique métier et ensuite nous allons ajouter Spring AOP pour profiler notre fonction métier. Ouvrez l’interface Metier.java et copier le code ci-dessous :


package com.soat.spring.aop.demo;

public interface Metier {

   void jeTravaille();

}

Maintenant, ouvrez le MetierImpl.java et copiez-y le code ci-dessous :


package com.soat.spring.aop.demo;

import org.apache.log4j.Logger;

public class MetierImpl implements Metier {
   static final Logger logger = Logger.getLogger(MetierImpl.class);
   int res = 20;

   public int jeTravaille() {

      logger.info("debut traitement metiers");
      try {
         // traitements métiers
         logger.info("traitement metiers en cours");
         res++;
         Thread.sleep(3500);
      } catch (InterruptedException e) {
         logger.error("Erreur lors du traitement métier";
         return 0;
      }

      logger.info("Fin traitement metiers");
      return res;
   }

}

Ce code est assez explicite. Notre méthode dort juste pour quelques secondes et affiche un texte sur la console.

Un aspect spring pour profiler notre fonction

Écrivons maintenant un aspect qui va profiler notre fonction “jeTravaille ()”. On va utiliser le greffon @ Around ( advice en anglais) (Perdu dans le jargon ? Spring AOP basics ). Ouvrez le fichier “MetierProfiler.java” et copiez-y le code ci-dessous :


package com.soat.spring.aop.demo;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class MetierProfiler {
   static final Logger logger = Logger.getLogger(MetierProfiler.class);

   @Pointcut("execution(* com.soat.spring.aop.demo.*.*(..))")
   public void fonctionMetier() {
   }

   @Around("fonctionMetier()")
   public Object profile(ProceedingJoinPoint joinPoint) throws Throwable {
      long debut = System.currentTimeMillis();

      logger.info("Apelle de la fonction ...");
      Object sortie = joinPoint.proceed();

      logger.info("Fonction executee avec succees ...");
      long tempsPasse = System.currentTimeMillis() - debut;

      logger.info("Temps d'exécution de la fonction: "; 
               + tempsPasse
               + " milliseconds.");

      return sortie;
   }

}

Voici ce que ce code fait :

  1. Utilisation de l’annotation @AspectJ pour déclarer que cette classe est un aspect.
  2. En utilisant l’annotation @Pointcut, nous avons défini une “pointcut” qui correspond à l’exécution de toutes les méthodes publiques appartenant au package com.soat.spring.aop.demo [ point de coupure]
  3. Utilisation de l’annotation @Around pour définir un greffon qui sera appelé avant et après notre fonction métier. Le greffon @Around va envelopper notre fonction.

Configuration de Spring AOP et @AspectJ

Ouvrez le fichier applicationContext.xml et copiez le code ci-dessous :


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:aop="http://www.springframework.org/schema/aop"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

   <!-- @AspectJ support -->
   <aop:aspectj-autoproxy />

    <bean id="MetierProfiler" class="com.soat.spring.aop.demo.MetierProfiler" />
    <bean id="classMetier" class="com.soat.spring.aop.demo.MetierImpl" />
</beans>

Voici ce que nous faisons dans le fichier XML ci-dessus:

  1. Nous avons ajouté les schémas AOP nécessaires sur le haut du fichier XML.
  2. Avec  <aop:aspectj-autoproxy />, nous avons activé le support @ AspectJ pour notre application.
  3. Et puis nous avons défini deux beans Spring normaux – un pour notre classe métier et l’autre pour notre métier Profiler (c’est à dire notre aspect).

Félicitations nous avons fini ! A ce stade, nous avons ajouté avec succès Spring AOP à notre projet et nous l’avons configuré. Dans l’étape suivante, nous allons pouvoir tester notre code !

Testons notre Spring AOP profiler

Pour cela nous allons ajouter un test unitaire Junit. Les dépendances nécessaires ont été déjà ajoutées dans le pom maven. Créez juste un nouveau test “ProfilingMetierTestCase.java”  et copiez-y les lignes ci-dessous :

package com.soat.spring.aop.demo.test;

import static org.junit.Assert.*;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.soat.spring.aop.demo.Metier;

public class ProfilingMetierTestCase {

   @Test
   public void test() {
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       int rec;
       Metier t1 = (Metier) context.getBean("classMetier");
       rec = t1.jeTravaille();
       assertEquals(21, rec);
   }
}

Dans le code ci-dessus nous chargeons notre bean Métier à partir du context spring, puis on appelle notre fonction. Si vous exécutez ce test, on voit produire sur la console :


1786 [main] INFO  com.soat.spring.aop.demo.MetierProfiler  - Apelle de la fonction ...
1786 [main] INFO  com.soat.spring.aop.demo.MetierImpl  - debut traitement metiers
1786 [main] INFO  com.soat.spring.aop.demo.MetierImpl  - traitement metiers en cours
5287 [main] INFO  com.soat.spring.aop.demo.MetierImpl  - Fin traitement metiers
5287 [main] INFO  com.soat.spring.aop.demo.MetierProfiler  - Fonction executee avec succees ...
5287 [main] INFO  com.soat.spring.aop.demo.MetierProfiler  - Temps d'exécution de la fonction: 3501 milliseconds.

Spring AOP Flow – expliqué dans un diagramme de séquence

Conclusion

Spring Aop offre bien plus de fonctionnalités qui vous permettent de séparer les préoccupations transverses. On peut se préoccuper que de l’aspect de l’application qui nous concerne, ce qui simplifie le travail, et permet d’augmenter la parallélisation du développement.

L’apprentissage de Spring Aop demande un certain temps mais le ROTI (Return Of Time Invested ) est considérable.
J’espère que ce tutoriel vous aidera à comprendre les bases de la programmation Orientée Aspect Spring. Si vous avez des questions le concernant, n’hésitez pas à laisser un commentaire.

Nombre de vue : 537

COMMENTAIRES 2 commentaires

  1. Jean dit :

    Bonjour,

    Merci pour ton article. J’ai une question sur les performances de Spring AOP. Est ce qu’utiliser Spring AOP va (vraiment) dégrader les performances de ton application? Est ce que tu as pu mesurer si les performances de logger avec Spring AOP sont “mauvaises”?

    Merci

    Jean

  2. nour R dit :

    merci pour cette article.
    Mais j’ai une question sur la modélisation des aspect(advice, point cut,aspect)avec les outils de modélisation comme Magic draw.

AJOUTER UN COMMENTAIRE