Java EE - EPSI POE mars 2017 - David Gayerie Licence Creative Commons

Les annotations

  1. Utilisation des annotations
  2. Déclaration d'une annotation
  3. Rétention d'une annotation
  4. Exercice : framework de tests unitaires

Les annotations en Java sont des marqueurs qui permettent d'ajouter des méta-données aux classes, aux méthodes, aux attributs, aux paramètres, aux variables, aux paquets ou aux annotations elles-mêmes.

Les annotations sont utilisées dans des domaines divers. Leur intérêt principal est de fournir une méta-information qui pourra être exploitée par un programme.

Utilisation des annotations

Une annotation est un type (comme une classe ou une interface) du langage Java : elle peut être référencée par son nom complet ou importée depuis un autre paquet grâce au mot-clé import.

Une annotation n'est pas instanciée, elle est simplement accolée à l'élément qu'elle vient enrichir :


import java.io.IOException;

import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// Une annotation de classe
@WebServlet("/MyServlet")
public class MyServlet extends HttpServlet {

  // Une annotation sur un attribut
  @EJB
  private IndividuRepository individuRepository;

  // Une annotation sur une méthode
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
    // ...
  }

}

Certaines annotations déclarent des attributs (par exemple l'annotation javax.servlet.annotation.WebServlet)


@WebServlet(urlPatterns = "/MyServlet", loadOnStartup = 1, displayName = "Ma servlet à moi")
public class MyServlet extends HttpServlet {
  // ...
}

Par convention, si un attribut de l'annotation s'appelle value et qu'il est le seul paramètre spécifié, alors son nom peut être omis pour plus de lisibilité.


  @SuppressWarnings("deprecation") 
  public void myMethod() {
    //...
  }

  @SuppressWarnings(value="deprecation") 
  public void myOtherMethod() {
    //...
  }

Un nombre très limité d'annotations sont exploitées directement par le compilateur.

On trouve les annotations déclarées dans le paquet java.lang :

Déclaration d'une annotation

Une déclaration d'annotation

public @interface MyAnnotation {
}

Une déclaration d'annotation avec attributs

public @interface MyAnnotation {
  String  name();
  boolean isOk();
  int[]   range() default {1, 2, 3};
}

Une annotation implémente implicitement Annotation et rien d'autre !

Les attributs d'une annotation peuvent être uniquement :

Le mot-clé default permet de spécifier une valeur d'attribut par défaut.

Une annotation peut elle-même être annotée. Les annotations d'annotation fournies par Java 7 sont :

Rétention d'une annotation

Une annotation est définie par sa rétention, c'est-à-dire la façon dont une annotation sera conservée. Les différentes rétentions d'annotation sont :

source
L'annotation est accessible durant la compilation mais n'est pas intégrée dans le fichier class généré.
class
L'annotation est accessible durant la compilation, elle est intégrée dans le fichier class généré mais elle n'est pas chargée dans la JVM à l'exécution.
runtime
L'annotation est accessible durant la compilation, elle est intégrée dans le fichier class généré et elle est chargée dans la JVM à l'exécution. Elle est accessible par introspection.

Exercice : framework de tests unitaires

Objectif
Réaliser un framework d'exécution de tests unitaires. Ce framework doit appeler une à une les méthode publiques d'un objet qui portent l'annotation suivante :

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Désigne une méthode comme étant un test unitaire. 
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Test {
  String description();
}

Avant chaque appel, le framework écrit sur la sortie standard le contenu de l'attribut description.

On pourra utiliser la classe suivante pour créer le framework :


/**
 * Le framework de tests unitaires 
 */
public class UnitTestFramework {

  public void run(Object o) {
    // ...
  }

}

Pour exploiter les annotations de rétention runtime d'un objet, il faut utiliser l'API de reflexivité de Java afin de consulter la définition de la classe. On utilisera la méthode Object.getClass() héritée de Object.