SlideShare una empresa de Scribd logo
1 de 62
Descargar para leer sin conexión
14/12/2010
Sponsors
Les Annotations Java

                  Enfin 
                expliquées 
               simplement !




©Zenika                          3
Olivier Croisier
                                             J'aime 
  • Consultant Zenika                    tellement ses 
                                         quizz Java !
  • Certifié Java 5.0 (100%)
  • Certifié Spring Framework

  • Formateur certifié JavaSpecialist
    (javaspecialists.eu)
  • Formateur certifié Terracotta

  • Blog : The Coder's Breakfast
    ( thecodersbreakfast.net )
  • Twitter : @OlivierCroisier
                                        (Illustration. Effet dramatisé)
©Zenika                                                                   4
Plan


  •   Présentation
  •   Annotations, mode d'emploi
  •   Annotations personnalisées
  •   Outillage compile-time
  •   Outillage runtime
  •   Injection d'annotations
  •   Conclusion




©Zenika                            5
Plan


  • Présentation
      • Historique
      • Où trouver des annotations ?
  • Annotations, mode d'emploi
  • Annotations personnalisées
  • Outillage compile-time
  • Outillage runtime
  • Injection d'annotations
  • Conclusion




©Zenika                                6
Présentation
  Historique

  • Java a toujours proposé une forme ou une autre de méta-
    programmation

  • Dès l'origine, l'outil "javadoc" permettait d'exploiter
    automatiquement des méta-données à but documentaire

    /**
     /**
     ** Méthode inutile
          Méthode inutile
     ** @param param Un paramètre (non utilisé)
          @param param Un paramètre (non utilisé)
     ** @return Une valeur fixe :: "foo"
          @return Une valeur fixe   "foo"
     ** @throws Exception N'arrive jamais (promis!)
          @throws Exception N'arrive jamais (promis!)
     */*/
    public String foo(String param) throws Exception {{
     public String foo(String param) throws Exception
        return "foo";
         return "foo";
    }}

©Zenika                                                       7
Présentation
  Historique

  • Ce système était flexible et a rapidement été utilisé / détourné
    pour générer d'autres artefacts : fichiers de configuration, classes
    annexes...
      • Voir le projet XDoclet (xdoclet.sourceforfge.net)
    /**
     /**
     ** @ejb.bean
         @ejb.bean
     **     name="bank/Account"
             name="bank/Account"
     **     type="CMP"
             type="CMP"
     **     jndi-name="ejb/bank/Account"
             jndi-name="ejb/bank/Account"
     **     local-jndi-name="ejb/bank/LocalAccount"
             local-jndi-name="ejb/bank/LocalAccount"
     **     primkey-field="id"
             primkey-field="id"
     ** @ejb.transaction
         @ejb.transaction
     **     type="Required"
             type="Required"
     ** @ejb.interface
         @ejb.interface
     **     remote-class="test.interfaces.Account"
             remote-class="test.interfaces.Account"
     */
      */
©Zenika                                                                    8
Présentation
  Historique

  • Reconnaissant le besoin d'un système de méta-programmation
    plus robuste et plus flexible, Java 5.0 introduit les Annotations
  • Elles remplacent avantageusement les doclets dans tous les
    domaines – sauf bien sûr pour la génération de la Javadoc !
    public class PojoAnnotation extends Superclass {{
     public class PojoAnnotation extends Superclass
        @Override
         @Override
        public void overridenMethod() {{
         public void overridenMethod()
            super.overridenMethod();
             super.overridenMethod();
        }}
          @Deprecated
           @Deprecated
          public void oldMethod(){
           public void oldMethod(){
          }}
    }}
©Zenika                                                                 9
Présentation
  Où trouver des annotations ?

  • Java SE propose assez peu d'annotations en standard
      • @Deprecated, @Override, @SuppressWarnings
      • 4 méta-annotations dans java.lang.annotation
      • Celles définies par JAXB et Commons Annotations      @
                                                             @
  • Java EE en fournit une quantité impressionnante
      • Pour les EJB 3, les Servlets 3, CDI, JSF 2, JPA...   @

  • Les frameworks modernes en tirent également parti
      • Spring, Hibernate, CXF, Stripes...

  • Développez les vôtres !

©Zenika                                                          10
Plan


  • Présentation
  • Annotations, mode d'emploi
      • Elements annotables
      • Annoter une classe, une méthode ou un champ
      • Annoter un package
      • Paramètres d'annotations
      • Restrictions et astuces
  • Annotations personnalisées
  • Outillage compile-time
  • Outillage runtime
  • Injection d'annotations
  • Conclusion

©Zenika                                               11
Annotations, mode d'emploi
  Elements annotables

  • Les annotations peuvent être apposées sur les éléments
    suivants :
      • Les classes, interfaces et enums
      • Les propriétés de classes
      • Les constructeurs et méthodes
      • Les paramètres des constructeurs et méthodes
      • Les variables locales
      • … et d'autres éléments encore grâce à la JSR 308 (Java 7 8)

  • Mais aussi sur...
     • Les packages
     • Les annotations elles-mêmes (méta-annotations) !

©Zenika                                                               12
Annotations, mode d'emploi
  Annoter une classe, méthode ou champ

    @Deprecated
     @Deprecated
    public class Pojo {{
     public class Pojo
        @Deprecated
         @Deprecated
        private int foo;
         private int foo;
        @Deprecated
         @Deprecated
        public Pojo() {{
         public Pojo()
            @Deprecated
             @Deprecated
            int localVar ==0;
             int localVar   0;
        }}
          @Deprecated
           @Deprecated
          public int getFoo() {{
           public intfoo;
              return getFoo()
               return foo;
          }}
          public void setFoo(@Deprecated int foo) {{
           public void setFoo(@Deprecated int foo)
              this.foo ==foo;
               this.foo foo;
          }}
    }}

©Zenika                                                13
Annotations, mode d'emploi
  Annoter un package

  • Comment annoter un package ?

  • La déclaration d'un package est présente dans
    toutes les classes appartenant à ce package. Impossible d'y
    placer une annotation : risque de conflit ou d'information
    incomplète !

    @Foo
     @Foo
    package com.zenika.presentation.annotations;
     package com.zenika.presentation.annotations;
    public class ClassA {}
     public class ClassA {}
    @Bar
     @Bar
    package com.zenika.presentation.annotations;
     package com.zenika.presentation.annotations;
    public class ClassB {}
     public class ClassB {}

©Zenika                                                           14
Annotations, mode d'emploi
  Annoter un package

  • Solution : pour annoter un package, il faut créer
    un fichier spécial nommé package-info.java
  • Il contient uniquement la déclaration du package,
    accompagné de sa javadoc et de ses annotations


    /**
     /**
     ** Ce package contient le code source de
         Ce package contient le code source de
     ** la présentation sur les annotations.
         la présentation sur les annotations.
     */
      */
    @Foo
     @Foo
    @Bar
     @Bar
    package com.zenika.presentation.annotations;
     package com.zenika.presentation.annotations;


©Zenika                                                 15
Annotations, mode d'emploi
  Paramètres d'annotations

  • Les annotations peuvent prendre des paramètres

  • Ils peuvent être obligatoires ou facultatifs (ils prennent alors la
    valeur par défaut spécifiée par le développeur de l'annotation)

  • Les paramètres se précisent entre parenthèses, à la suite de
    l'annotation ; leur ordre n'est pas important
    @MyAnnotation( param1=value1, param2=value2... ))
     @MyAnnotation( param1=value1, param2=value2...
  • Si l'annotation ne prend qu'un paramètre, il est souvent possible
    d'utiliser une notation raccourcie
    @MyAnnotation( value ))
     @MyAnnotation( value

©Zenika                                                                   16
Annotations, mode d'emploi
  Paramètres d'annotations




    @WebInitParam( name="foo", value="bar" ))
     @WebInitParam( name="foo", value="bar"
©Zenika                                         17
Annotations, mode d'emploi
  Restrictions et astuces

  • Il est interdit d'annoter plusieurs fois un élément avec la même
    annotation. Pour contourner le problème, on peut recourir à des
    annotations "wrapper"

    @SecondaryTables({
     @SecondaryTables({
        @SecondaryTable(name="city"),
         @SecondaryTable(name="city"),
        @SecondaryTable(name="country")
         @SecondaryTable(name="country")
    })
     })
    public class Address
     public class Address
    {...}
     {...}
  • Il est possible de séparer l'@ du nom de l'annotation !
    @@
    /** Javadoc */
     /** Javadoc */
    Deprecated
     Deprecated
©Zenika                                                                18
Annotations, mode d'emploi
  Restrictions et astuces

  • Pour les paramètres :

          • Les valeurs des paramètres doivent être des "compile-time
            constants"...

            @MyAnnotation(answer == (true!=false) ?? 42 :: 0)
             @MyAnnotation(answer    (true!=false)    42    0)

          • … mais ne peuvent pas être null
            (Et personne ne sait pourquoi !)

            @MyAnnotation(param == null)
             @MyAnnotation(param    null)



©Zenika                                                                 19
Plan


  • Présentation
  • Annotations, mode d'emploi
  • Annotations personnalisées
      • Use-cases
      • Méta-annotations
      • Paramètres d'annotations
  • Outillage compile-time
  • Outillage runtime
  • Injection d'annotations
  • Conclusion




©Zenika                            20
Annotations personnalisées
  A quoi ça sert ?

  • Pourquoi développer des annotations personnalisées ?
     • Pour remplacer / compléter des fichiers de configuration XML
     • Pour simplifier ou générifier une portion de code en recourant
       à la méta-programmation
     • Pour appliquer des règles de compilation supplémentaires,
       grâce aux Annotation Processors


          • … parce que c'est fun !




©Zenika                                                                 21
Annotations personnalisées
  Syntaxe

  • Une annotation se déclare comme un type spécial d'interface
  • Elle sera compilée sous la forme d'une interface héritant de
    java.lang.annotation.Annotation

    public @interface MyAnnotation {{
     public @interface MyAnnotation
    }}


  • Il est ensuite possible de compléter l'annotation avec :
       • Des paramètres
                    •Pour véhiculer des données supplémentaires
          • Des méta-annotations
                    •Pour spécifier les conditions d'utilisation de l'annotation


©Zenika                                                                            22
Annotation personnalisées
  Paramètres d'annotations

  • Chaque paramètre se déclare sous la forme d'une méthode (non
    générique, sans paramètres et sans exceptions)

  • Il peut posséder une valeur par défaut (compile-time constant),
    déclarée grâce au mot-clé "default" ; il est alors optionnel.

    public @interface MyAnnotation {{
     public @interface MyAnnotation
       String message();
        String message();
       int answer() default 42;
        int answer() default 42;
    }}


    @MyAnnotation( message="Hello World" ))
     @MyAnnotation( message="Hello World"
    @MyAnnotation( message="Hello World", answer == 00 ))
     @MyAnnotation( message="Hello World", answer

©Zenika                                                               23
Annotation personnalisées
  Paramètres d'annotations

  • Si l'annotation ne possède qu'un seul paramètre nommé "value",
    il est possible d'utiliser une syntaxe raccourcie


    public @interface MyAnnotation {{
     public @interface MyAnnotation
       String value();
        String value();
    }}


    @MyAnnotation( "Hello World" ))
     @MyAnnotation( "Hello World"
    @MyAnnotation( value == "Hello World" ))
     @MyAnnotation( value    "Hello World"




©Zenika                                                              24
Annotation personnalisées
  Paramètres d'annotations

  • Comme dans toute interface, il est possible de définir des classes,
    interfaces ou enums internes

    public @interface MyAnnotation {{
     public @interface MyAnnotation
       int defaultAnswer == 42;
        int defaultAnswer    42;
       int answer() default defaultAnswer;
        int answer() default defaultAnswer;
       enum Season {SPRING, SUMMER, FALL, WINTER};
        enum Season {SPRING, SUMMER, FALL, WINTER};
       Season season();
        Season season();
    }}


    @MyAnnotation( season == MyAnnotation.Season.WINTER ))
     @MyAnnotation( season    MyAnnotation.Season.WINTER

©Zenika                                                               25
Annotation personnalisées
  Les Méta-Annotations : @Target

  • La méta-annotation @Target indique sur quels éléments de code
    l'annotation peut être apposée :

    @Target( ElementType[] ))
     @Target( ElementType[]
    public @interface MyAnnotation {{
     public @interface MyAnnotation
    }}


  • Exemple :

    @Target( {ElementType.TYPE, ElementType.METHOD} ))
     @Target( {ElementType.TYPE, ElementType.METHOD}
    public @interface MyAnnotation {{
     public @interface MyAnnotation
    }}


©Zenika                                                             26
Annotation personnalisées
  Les Méta-Annotations : @Target

  • Valeurs possibles pour l'enum ElementType :
     • TYPE
     • CONSTRUCTOR
     • FIELD
     • METHOD
     • PARAMETER
     • LOCAL_VARIABLE
     • ANNOTATION_TYPE (méta-annotation)
     • PACKAGE
     • TYPE_PARAMETER et TYPE_USE (JSR 308, Java 7 8)
         Ex: @English String @NonEmpty []

  • Si le paramètre n'est pas spécifié, l'annotation
    peut être utilisée partout (Ex : @Deprecated)
©Zenika                                                 27
Annotation personnalisées
  Les Méta-Annotations : @Retention

  • La méta-annotation @Retention indique la durée de vie de
    l'annotation
    @Retention( RetentionPolicy ))
     @Retention( RetentionPolicy
    public @interface MyAnnotation {{
     public @interface MyAnnotation
    }}

  • Exemple
    @Retention( RetentionPolicy.RUNTIME ))
     @Retention( RetentionPolicy.RUNTIME
    public @interface MyAnnotation {{
     public @interface MyAnnotation
    }}




©Zenika                                                        28
Annotation personnalisées
  Les Méta-Annotations : @Retention

  • Valeurs possibles pour l'enum RetentionPolicy :
     • SOURCE
     • CLASS (par défaut)
     • RUNTIME
                          compilation     class
                                        loading

           SOURCE

           CLASS

           RUNTIME




©Zenika                                               29
Annotation personnalisées
  Les Méta-Annotations : @Inherited

  • La méta-annotation @Inherited indique que l'annotation est
    héritée par les classes filles de la classe annotée

    @Inherited
     @Inherited
    public @interface MyAnnotation {{
     public @interface MyAnnotation
    }}


  • Restrictions
     • Seules les annotations portées sur les classes sont héritées
     • Les annotations apposées sur une interface ne sont pas
       héritées par les classes implémentant cette interface ; idem
       pour les packages.


©Zenika                                                               30
Annotation personnalisées
  Les Méta-Annotations : @Documented

  • La méta-annotation @Documented indique que l'annotation doit
    apparaître dans la javadoc

    @Documented
     @Documented
    public @interface MyAnnotation {{
     public @interface MyAnnotation
    }}




©Zenika                                                            31
Plan


  • Présentation
  • Anatomie
  • Mode d'emploi
  • Annotations personnalisées
  • Outillage compile-time
      • Historique et use-cases
      • Processus de compilation
      • Anatomie d'un processeur
      • Limitations
  • Outillage runtime
  • Injection d'annotations
  • Conclusion

©Zenika                            32
Outillage compile-time
  Historique et use-cases

  Historique

  • Java 5.0 : APT (Annotation Processing Tool)
      • Devait être lancé en plus du compilateur javac

  • Java 6.0 : Pluggable Annotation Processors
      • Intégrés au processus de compilation standard
      • Paramètre -processor ou utilisation du SPI (Service Provider
        Interface)

                Pour plus d'informations sur le SPI, voir :
                • Un article sur The Coder's Breakfast
                • La Javadoc de java.util.ServiceLoader

©Zenika                                                                33
Outillage compile-time
  Historique et use-cases

  Use-cases

  • Génération de ressources : "XDoclet ++"
     • Fichiers de configuration
     • Classes annexes
                   •Ex: Proxies, PropertyEditors...
          • Documentation
                   •Ex: Matrice des rôles JavaEE, cartographie d'IOC...

  • Amélioration du compilateur
     • Vérification de normes de codage
                   •Ex: Les classes "modèle" doivent être Serializable...
          • Messages d'alerte ou d'erreur supplémentaires

©Zenika                                                                     34
Outillage compile-time
  Historique et use-cases

  Mention spéciale : Lombok (projectlombok.org)

          • Améliore "magiquement" les classes
                      •Génère les getters/setters, equals/hashCode, toString
          • Viole la règle de non-modification des ressources existantes
          • Dépend des implémentations internes des compilateurs pour
            manipuler les AST des classes
                      •com.sun.tools.javac.*
                      •org.eclipse.jdt.internal.compiler.*

          • Danger : la compilation de votre projet dépend désormais du
            support de votre compilateur cible par Lombok.
            Peser le rapport gain / risques !
                     •Votre IDE propose également ces fonctionnalités !
©Zenika                                                                        35
Outillage compile-time
  Processus de compilation


          1. Le compilateur découvre les processeurs d'annotations
                    •Paramètre -processor sur la ligne de commande
                    •ou via le Service Provider Interface (SPI)

          2. Un round de compilation est lancé
                    •Le compilateur et les processeurs s'exécutent
                    •Si de nouvelles ressources sont créées lors de ce round,
                    un nouveau round est lancé




©Zenika                                                                         36
Outillage compile-time
  Anatomie d'un Processeur

  • Un processeur est une classe implémentant l'interface
    javax.annotation.processing.Processor
      • Généralement, on sous-classe AbstractProcessor

  • L'annotation @SupportedAnnotationTypes permet d'indiquer
    quelles annotations le processeur sait traiter

  • La méthode init() permet d'initialiser le processeur

  • La méthode principale process() reçoit un paramètre de type
    RoundEnvironment représentant l'environnement de compilation.
    Elle renvoie un booléen indiquant si l'annotation est définitivement
    "consommée" par ce processeur

©Zenika                                                                    37
Outillage compile-time
  Anatomie d'un Processeur

  • Des utilitaires sont accessibles via la propriété processingEnv
    fournie par AbstractProcessor :


          • Types et Elements, permettant d'introspecter le code
          • Messager, pour lever des erreurs de compilation et afficher des
            messages dans la console
          • Filer, autorisant la création de nouvelles ressources (classes,
            fichiers de configuration...)

    Types
     Types        types
                   types      == processingEnv.getTypeUtils();
                                  processingEnv.getTypeUtils();
    Elements
     Elements     elts
                   elts       == processingEnv.getElementUtils();
                                  processingEnv.getElementUtils();
    Messager
     Messager     messager
                   messager   == processingEnv.getMessager();
                                  processingEnv.getMessager();
    Filer
     Filer        filer
                   filer      == processingEnv.getFiler();
                                  processingEnv.getFiler();

©Zenika                                                                   38
Outillage compile-time
  Anatomie d'un Processeur
    @SupportedAnnotationTypes("com.zenika.*")
     @SupportedAnnotationTypes("com.zenika.*")
    public class MyProcessor extends AbstractProcessor {{
     public class MyProcessor extends AbstractProcessor
        Types types;
         Types types;
        Elements elements;
         Elements elements;
        Messager messager;
         Messager messager;
        Filer filer;
         Filer filer;
          public void init(ProcessingEnvironment processingEnv) {{
           public void init(ProcessingEnvironment processingEnv)
              super.init(processingEnv);
               super.init(processingEnv);
              types
               types    == processingEnv.getTypeUtils();
                            processingEnv.getTypeUtils();
              elements == processingEnv.getElementUtils();
               elements     processingEnv.getElementUtils();
              messager == processingEnv.getMessager();
               messager = processingEnv.getFiler();
                            processingEnv.getMessager();
              filer
               filer     = processingEnv.getFiler();
          }}
          public boolean process(
           public boolean process(
             Set<? extends TypeElement> annotations,
             RoundEnvironment roundEnv) {annotations,
              Set<? extends TypeElement>
              RoundEnvironment roundEnv) {
                 // TODO
             }} // TODO
    }}
©Zenika                                                              39
Outillage compile-time
  Anatomie d'un Processeur

    public boolean process(
     public boolean process(
       Set<? extends TypeElement> annotations,
        Set<? extends TypeElement> annotations,
       RoundEnvironment roundEnv) {{
        RoundEnvironment roundEnv)
       // Pour chaque annotation traitée...
        // Pour chaque annotation traitée...
       for (TypeElement annotation :: annotations) {{
        for (TypeElement annotation     annotations)
           // Trouver les éléments portant cette annotation
            // Trouver les éléments portant cette annotation
           for (Element ee ::
            for (Element
              roundEnv.getElementsAnnotatedWith(annotation)) {{
               roundEnv.getElementsAnnotatedWith(annotation))
              messager.printMessage(
               messager.printMessage(
                  Diagnostic.Kind.NOTE,
                   Diagnostic.Kind.NOTE,
                  e.getSimpleName());
                   e.getSimpleName());
           }}
       }}
       return false;
        return false;
    }}
©Zenika                                                           40
Outillage compile-time
  Limitations

  • Développer un processeur est complexe !
     • Les Types et les Elements offrent deux vues différentes sur le
       code compilé
                     •Les Elements représentent l'AST brut du code
                     •Les Types offrent une interface davantage typée "java"
                     •Il existe des ponts entre ces deux univers
          • Le pattern Visiteur est beaucoup utilisé

  • Un processeur ne peut pas
    modifier du code existant !

  • Quelques bugs encore, et un
    faible support dans les IDE

©Zenika                                                                        41
Outillage compile-time
  Démos


  Démos
  • ListingProcessor
  •MessageHolderProcessor
  •SerializableClassesProcessor




©Zenika                           42
Plan


  • Présentation
  • Annotations, mode d'emploi
  • Annotations personnalisées
  • Outillage compile-time
  • Outillage runtime
      • Use-cases
      • Récupération des paramètres
      • Une fois les annotations récupérées...
  • Injection d'annotations
  • Conclusion




©Zenika                                          43
Outillage runtime
  Use-cases

  • Au runtime, il est possible d'utiliser la Réflexion pour découvrir les
    annotations présentes sur les classes, champs, méthodes et
    paramètres de méthodes.
  • Uniquement si @Retention(RetentionPolicy.RUNTIME)

  • Use-cases :
     • Mapping Java ↔ ?
     • Programmation orientée POJO
     • Configuration de containers / frameworks

  • Exemples :
     • Hibernate, Apache CXF, XStream...
     • Spring, Guice, Java EE 5/6 (CDI, EJB 3.0, Servlets 3.0...)
©Zenika                                                                      44
Outillage runtime
  Récupération des annotations

  • Les classes Package, Class, Constructor, Field et Method
    implémentent l'interface AnnotatedElement :

    public interface AnnotatedElement {{
     public interface AnnotatedElement
       Annotation[] getAnnotations();
        Annotation[] getAnnotations();
       Annotation[] getDeclaredAnnotations();
        Annotation[] getDeclaredAnnotations();
       boolean isAnnotationPresent(Class annotationClass);
        boolean isAnnotationPresent(Class annotationClass);
       Annotation getAnnotation(Class annotationClass);
        Annotation getAnnotation(Class annotationClass);
    }}

          • getAnnotations() renvoie toutes les annotations applicables à
            l'élément, y compris les annotations héritées
          • getDeclaredAnnotations() ne renvoie que les annotations
            directement apposées sur l'élément


©Zenika                                                                 45
Outillage runtime
  Récupération des annotations

  • Exemple : lecture des annotations d'une classe et de celles de
    son package

    // Annotations sur la classe
     // Annotations sur la classe
    Annotation[] clsAnnots == Pojo.class.getAnnotations();
     Annotation[] clsAnnots    Pojo.class.getAnnotations();
    for (Annotation annot :: clsAnnots) {{
     for (Annotation annot    clsAnnots)
       System.out.println(annot);
        System.out.println(annot);
    }}
    // Annotations sur le package
     // Annotations sur le package
    Package pkg == Pojo.class.getPackage();
     Package pkg    Pojo.class.getPackage();
    Annotation[] pkgAnnots == pkg.getDeclaredAnnotations();
     Annotation[] pkgAnnots    pkg.getDeclaredAnnotations();
    for (Annotation annot :: pkgAnnots) {{
     for (Annotation annot    pkgAnnots)
       System.out.println(annot);
        System.out.println(annot);
    }}


©Zenika                                                              46
Outillage runtime
  Récupération des annotations

  • Les classes Constructor et Method permettent également de
    récupérer les annotations présentes sur leurs paramètres
      • Annotation[][] getParameterAnnotations()
      • Renvoie un tableau d'annotations par paramètre, dans l'ordre
        de leur déclaration dans la signature de la méthode

    public void printParamAnnots(Method method) {{
     public void printParamAnnots(Method method)
       Annotation[][] paramAnnots ==
        Annotation[][] paramAnnots
          method.getParameterAnnotations();
           method.getParameterAnnotations();
       for (Annotation[] annots :: paramAnnots) {{
        for (Annotation[] annots    paramAnnots)
          System.out.println(Arrays.toString(annots));
           System.out.println(Arrays.toString(annots));
       }}
    }}
©Zenika                                                                47
Outillage runtime
  Une fois les annotations récupérées...

  • Que peut-on faire avec les annotations récupérées par réflexion ?
     • On peut découvrir leur type dynamiquement
       Class<? extends Annotation> annotationType()
     • On peut lire leurs paramètres (cast nécessaire)

    Annotation annot == …… ;;
     Annotation annot
    // Détermination du type réel de l'annotation
     // Détermination du type réel de l'annotation
    Class<? extends Annotation> annotClass ==
     Class<? extends Annotation> annotClass
       myAnnotation.annotationType();
        myAnnotation.annotationType();
    // Affichage du message de MyAnnotation
     // Affichage du message de MyAnnotation
    if (annot instanceof MyAnnotation) {{
     if (annot instanceof MyAnnotation)
       MyAnnotation myAnnot == (MyAnnotation) annot;
        MyAnnotation myAnnot    (MyAnnotation) annot;
       System.out.println(myAnnot.message());
        System.out.println(myAnnot.message());
    }}
©Zenika                                                                 48
Outillage runtime
  Démos



  Démos
  • Démonstration
  • Exemple : CSVReader




©Zenika                   49
Plan


  • Présentation
  • Mode d'emploi
  • Annotations personnalisées
  • Outillage compile-time
  • Outillage runtime
  • Injection d'annotations
      • Au coeur de la classe Class
      • Instancier dynamiquement une annotation
      • Injection dans une classe
      • Injection sur une méthode ou un champ
  • Conclusion


©Zenika                                           50
Injection d'annotations
  Au coeur de la classe Class

  • Dans la classe Class, les annotations sont représentées sous la
    forme de Maps :
    private transient Map<Class, Annotation> annotations;
     private transient Map<Class, Annotation> annotations;
    private transient Map<Class, Annotation> declaredAnnotations;
     private transient Map<Class, Annotation> declaredAnnotations;

  • Ces maps sont initialisées lors du premier appel à
    getAnnotations() ou getDeclaredAnnotations()
  • L'initialisation est réalisée en décodant le byte[] renvoyé par la
    méthode native getRawAnnotations()

  • En modifiant ces maps par Réflexion,
    il est possible d'injecter arbitrairement
    des annotations sur une Classe au runtime !

©Zenika                                                                  51
Injection d'annotations
  Instancier une annotation

  • Pour obtenir une instance de l'annotation à injecter, il suffit
    d'instancier une classe anonyme implémentant son "interface"

    MyAnnotation myAnnotation == new MyAnnotation() {{
     MyAnnotation myAnnotation    new MyAnnotation()
        @Override
         @Override
        public String message() {{
         public String message()
            return MyAnnotation.defaultMessage;
        }} return MyAnnotation.defaultMessage;
        @Override
         @Override
        public int answer() {{
         public intMyAnnotation.defaultAnswer;
                    answer()
            return MyAnnotation.defaultAnswer;
        }} return
          @Override
           @Override
          public Class<? extends Annotation> annotationType() {{
           public Class<? extends Annotation> annotationType()
              return MyAnnotation.class;
          }} return MyAnnotation.class;
    };
     };
©Zenika                                                               52
Injection d'annotations
  Instancier une annotation

  • Attention, les annotations créées programmatiquement doivent
    implémenter les méthodes equals() et hashCode() en respectant
    le contrat décrit dans la Javadoc.

  • hashCode() :
      • "The hash code of an annotation is the sum of the hash codes
        of its members (including those with default values)"

  • equals() :
      • "Returns true if the specified object is an instance of the same
        annotation type as this instance, all of whose members are
        equal to the corresponding member of this annotation"



©Zenika                                                                    53
Injection d'annotations
  Injection sur une Classe

  • Il ne reste plus qu'à utiliser la Réflexion pour injecter notre
    annotation dans la classe cible
    public static void injectClass
     public statictargetClass, Annotation annotation) {
                   void injectClass
        (Class<?> targetClass, Annotation annotation) {
         (Class<?>
        // Initialisation des maps d'annotations
         // Initialisation des maps d'annotations
        targetClass.getAnnotations();
         targetClass.getAnnotations();
        // Récupération de la map interne des annotations
         // Récupération de la map interne des annotations
        Field mapRef == Class.class.getDeclaredField("annotations");
         Field mapRef    Class.class.getDeclaredField("annotations");
        mapRef.setAccessible(true);
         mapRef.setAccessible(true);
        // Modification de la map des annotations
        Map<Class, Annotation> map des=annotations
         // Modification de la annots
         Map<Class, Annotation> annots =
            (Map<Class, Annotation>) mapRef.get(targetClass);
        if (annots==null Annotation>) mapRef.get(targetClass);
             (Map<Class, || annots.isEmpty()) {
         if annots = new HashMap<Class, Annotation>();
            (annots==null || annots.isEmpty()) {
        }} annots = new HashMap<Class, Annotation>();
        pojoAnnotations.put(annotation.annotationType(), annotation);
         pojoAnnotations.put(annotation.annotationType(), annotation);
        mapRef.set(targetClass, pojoAnnotations);
    }} mapRef.set(targetClass, pojoAnnotations);
©Zenika                                                                  54
Injection d'annotations
  Injection sur une Méthode ou un Champ

  • L'injection d'annotations sur les classes Constructor, Field et
    Method est plus problématique

  • Au sein de la classe Class, les méthodes getConstructor(),
    getField(), ou getMethod() renvoient des copies des objets
    correspondants
    Method m1 == Pojo.class.getDeclaredMethod("foo", null);
     Method m1    Pojo.class.getDeclaredMethod("foo", null);
    Method m2 == Pojo.class.getDeclaredMethod("foo", null);
     Method m2    Pojo.class.getDeclaredMethod("foo", null);
    System.out.println(m1==m2); // false
     System.out.println(m1==m2); // false

  • Ces copies sont initialisées directement à partir du bytecode de la
    classe, pas à partir d'une instance prééxistante
  • Les modifications apportées aux maps d'annotations sur une
    instance sont donc strictement locales à cette instance

©Zenika                                                                   55
Injection d'annotations
  Injection sur une Méthode ou un Champ

  • Alors, comment faire ?
      • AOP pour intercepter les méthodes getConstructor(),
        getMethod(), getField() ?
      • Modifier directement la portion de bytecode
        correspondant à ces objets ?
      • Si vous trouvez une solution,
        je suis preneur !




©Zenika                                                       56
Injection d'annotations
  Use-cases

  • Use-cases

          • Les annotations @Inherited posées sur les
            interfaces ne sont pas héritées par les classes
            implémentant ces interfaces.
            Il est possible d'y remédier en réinjectant
            manuellement ces annotations dans les
            classes. Mais attention aux conflits !
          • Idem pour les annotations posées sur les
            packages

          • … d'autres idées ?


©Zenika                                                       57
Injection d'annotations
  Démos


  Démos
  • Injection dans une classe
  • Injection dans un champ




©Zenika                         58
Plan


  •   Présentation
  •   Mode d'emploi
  •   Annotations personnalisées
  •   Outillage compile-time
  •   Outillage runtime
  •   Injection d'annotations
  •   Conclusion




©Zenika                            59
Conclusion


  • Les doclets ont ouvert la voie à la méta-programmation ;
    Java 5.0 a standardisé et démocratisé les annotations

  • Tous les frameworks modernes utilisent les annotations
  • Elles complètent parfaitement les fichiers de configuration XML

  • Il est facile de développer des
    annotations personnalisées
  • Java fournit des outils pour les
    exploiter lors de la compilation
    et au runtime

  • Mais attention à la complexité !

©Zenika                                                               60
?
  Conclusion




               Questions / Réponses
©Zenika                               61
Références


  • Annotation processors
     • La documentation du SDK et la JLS
     • "Enforcing design rules with Pluggable Annotation
       Processors" sur http://thecodersbreakfast.net
     • La newsletter Javaspecialists (http://javaspecialists.eu)

  • JSR 308 et le framework Checkers
      • http://types.cs.washington.edu/jsr308/

  • Lombok
      • http://projectlombok.org/



©Zenika                                                            62

Más contenido relacionado

La actualidad más candente

JMockit Framework Overview
JMockit Framework OverviewJMockit Framework Overview
JMockit Framework OverviewMario Peshev
 
Formation Spring Avancé gratuite par Ippon 2014
Formation Spring Avancé gratuite par Ippon 2014Formation Spring Avancé gratuite par Ippon 2014
Formation Spring Avancé gratuite par Ippon 2014Ippon
 
L'API Collector dans tous ses états
L'API Collector dans tous ses étatsL'API Collector dans tous ses états
L'API Collector dans tous ses étatsJosé Paumard
 
Java 8 - Features Overview
Java 8 - Features OverviewJava 8 - Features Overview
Java 8 - Features OverviewSergii Stets
 
Tester unitairement une application java
Tester unitairement une application javaTester unitairement une application java
Tester unitairement une application javaAntoine Rey
 
Curso de RESTful WebServices em Java com JAX-RS (Java EE 7)
Curso de RESTful WebServices em Java com JAX-RS (Java EE 7)Curso de RESTful WebServices em Java com JAX-RS (Java EE 7)
Curso de RESTful WebServices em Java com JAX-RS (Java EE 7)Helder da Rocha
 
Spring Data JPA from 0-100 in 60 minutes
Spring Data JPA from 0-100 in 60 minutesSpring Data JPA from 0-100 in 60 minutes
Spring Data JPA from 0-100 in 60 minutesVMware Tanzu
 
Java Serialization Deep Dive
Java Serialization Deep DiveJava Serialization Deep Dive
Java Serialization Deep DiveMartijn Dashorst
 
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드 Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드 SangIn Choung
 
[TDC2016] Ruby in Tests: Automatizando testes de Unidade, API e GUI (Web)
[TDC2016] Ruby in Tests: Automatizando testes de Unidade, API e GUI (Web)[TDC2016] Ruby in Tests: Automatizando testes de Unidade, API e GUI (Web)
[TDC2016] Ruby in Tests: Automatizando testes de Unidade, API e GUI (Web)Júlio de Lima
 
Curso de Java Persistence API (JPA) (Java EE 7)
Curso de Java Persistence API (JPA) (Java EE 7)Curso de Java Persistence API (JPA) (Java EE 7)
Curso de Java Persistence API (JPA) (Java EE 7)Helder da Rocha
 
Les dessous du framework spring
Les dessous du framework springLes dessous du framework spring
Les dessous du framework springAntoine Rey
 
Extending Java EE with CDI and JBoss Forge
Extending Java EE with CDI and JBoss ForgeExtending Java EE with CDI and JBoss Forge
Extending Java EE with CDI and JBoss ForgeAntoine Sabot-Durand
 
An Introduction to Maven
An Introduction to MavenAn Introduction to Maven
An Introduction to MavenVadym Lotar
 

La actualidad más candente (20)

JMockit Framework Overview
JMockit Framework OverviewJMockit Framework Overview
JMockit Framework Overview
 
Formation Spring Avancé gratuite par Ippon 2014
Formation Spring Avancé gratuite par Ippon 2014Formation Spring Avancé gratuite par Ippon 2014
Formation Spring Avancé gratuite par Ippon 2014
 
Optional in Java 8
Optional in Java 8Optional in Java 8
Optional in Java 8
 
Spring Data Jpa
Spring Data JpaSpring Data Jpa
Spring Data Jpa
 
L'API Collector dans tous ses états
L'API Collector dans tous ses étatsL'API Collector dans tous ses états
L'API Collector dans tous ses états
 
Java 8 - Features Overview
Java 8 - Features OverviewJava 8 - Features Overview
Java 8 - Features Overview
 
Spring jdbc
Spring jdbcSpring jdbc
Spring jdbc
 
Complete Java Course
Complete Java CourseComplete Java Course
Complete Java Course
 
Tester unitairement une application java
Tester unitairement une application javaTester unitairement une application java
Tester unitairement une application java
 
Curso de RESTful WebServices em Java com JAX-RS (Java EE 7)
Curso de RESTful WebServices em Java com JAX-RS (Java EE 7)Curso de RESTful WebServices em Java com JAX-RS (Java EE 7)
Curso de RESTful WebServices em Java com JAX-RS (Java EE 7)
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Spring Data JPA from 0-100 in 60 minutes
Spring Data JPA from 0-100 in 60 minutesSpring Data JPA from 0-100 in 60 minutes
Spring Data JPA from 0-100 in 60 minutes
 
Java Serialization Deep Dive
Java Serialization Deep DiveJava Serialization Deep Dive
Java Serialization Deep Dive
 
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드 Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
Postman과 Newman을 이용한 RestAPI 테스트 자동화 가이드
 
[TDC2016] Ruby in Tests: Automatizando testes de Unidade, API e GUI (Web)
[TDC2016] Ruby in Tests: Automatizando testes de Unidade, API e GUI (Web)[TDC2016] Ruby in Tests: Automatizando testes de Unidade, API e GUI (Web)
[TDC2016] Ruby in Tests: Automatizando testes de Unidade, API e GUI (Web)
 
Curso de Java Persistence API (JPA) (Java EE 7)
Curso de Java Persistence API (JPA) (Java EE 7)Curso de Java Persistence API (JPA) (Java EE 7)
Curso de Java Persistence API (JPA) (Java EE 7)
 
Les dessous du framework spring
Les dessous du framework springLes dessous du framework spring
Les dessous du framework spring
 
Extending Java EE with CDI and JBoss Forge
Extending Java EE with CDI and JBoss ForgeExtending Java EE with CDI and JBoss Forge
Extending Java EE with CDI and JBoss Forge
 
JUnit 4
JUnit 4JUnit 4
JUnit 4
 
An Introduction to Maven
An Introduction to MavenAn Introduction to Maven
An Introduction to Maven
 

Destacado

Pluggable annotation processing api
Pluggable annotation processing apiPluggable annotation processing api
Pluggable annotation processing apiArnaud Tournier
 
Type Annotations in Java 8
Type Annotations in Java 8 Type Annotations in Java 8
Type Annotations in Java 8 FinLingua, Inc.
 
Speech Technology and Big Data
Speech Technology and Big DataSpeech Technology and Big Data
Speech Technology and Big DataEUCLID project
 
Big Linked Data - Creating Training Curricula
Big Linked Data - Creating Training CurriculaBig Linked Data - Creating Training Curricula
Big Linked Data - Creating Training CurriculaEUCLID project
 
Online Learning and Linked Data: An Introduction
Online Learning and Linked Data: An IntroductionOnline Learning and Linked Data: An Introduction
Online Learning and Linked Data: An IntroductionEUCLID project
 
Best Practices for Linked Data Education
Best Practices for Linked Data EducationBest Practices for Linked Data Education
Best Practices for Linked Data EducationEUCLID project
 
Data Science Curriculum for Professionals
Data Science Curriculum for ProfessionalsData Science Curriculum for Professionals
Data Science Curriculum for ProfessionalsEUCLID project
 
Microtask Crowdsourcing Applications for Linked Data
Microtask Crowdsourcing Applications for Linked DataMicrotask Crowdsourcing Applications for Linked Data
Microtask Crowdsourcing Applications for Linked DataEUCLID project
 
Mapping Relational Databases to Linked Data
Mapping Relational Databases to Linked DataMapping Relational Databases to Linked Data
Mapping Relational Databases to Linked DataEUCLID project
 
Relational Database to RDF (RDB2RDF)
Relational Database to RDF (RDB2RDF)Relational Database to RDF (RDB2RDF)
Relational Database to RDF (RDB2RDF)EUCLID project
 
Annotation Processor, trésor caché de la JVM
Annotation Processor, trésor caché de la JVMAnnotation Processor, trésor caché de la JVM
Annotation Processor, trésor caché de la JVMRaphaël Brugier
 
Querying Linked Data on Android
Querying Linked Data on AndroidQuerying Linked Data on Android
Querying Linked Data on AndroidEUCLID project
 
Scaling up Linked Data
Scaling up Linked DataScaling up Linked Data
Scaling up Linked DataEUCLID project
 
Interaction with Linked Data
Interaction with Linked DataInteraction with Linked Data
Interaction with Linked DataEUCLID project
 
פתרון חורף 2017 שאלון 806
פתרון חורף 2017 שאלון 806פתרון חורף 2017 שאלון 806
פתרון חורף 2017 שאלון 806Dmitri Aerov
 
Java Annotation Processing: A Beginner Walkthrough
Java Annotation Processing: A Beginner WalkthroughJava Annotation Processing: A Beginner Walkthrough
Java Annotation Processing: A Beginner WalkthroughMahfuz Islam Bhuiyan
 

Destacado (20)

Pluggable annotation processing api
Pluggable annotation processing apiPluggable annotation processing api
Pluggable annotation processing api
 
Java annotation
Java annotationJava annotation
Java annotation
 
Type Annotations in Java 8
Type Annotations in Java 8 Type Annotations in Java 8
Type Annotations in Java 8
 
Speech Technology and Big Data
Speech Technology and Big DataSpeech Technology and Big Data
Speech Technology and Big Data
 
Big Linked Data - Creating Training Curricula
Big Linked Data - Creating Training CurriculaBig Linked Data - Creating Training Curricula
Big Linked Data - Creating Training Curricula
 
Online Learning and Linked Data: An Introduction
Online Learning and Linked Data: An IntroductionOnline Learning and Linked Data: An Introduction
Online Learning and Linked Data: An Introduction
 
Best Practices for Linked Data Education
Best Practices for Linked Data EducationBest Practices for Linked Data Education
Best Practices for Linked Data Education
 
Data Science Curriculum for Professionals
Data Science Curriculum for ProfessionalsData Science Curriculum for Professionals
Data Science Curriculum for Professionals
 
Providing Linked Data
Providing Linked DataProviding Linked Data
Providing Linked Data
 
Microtask Crowdsourcing Applications for Linked Data
Microtask Crowdsourcing Applications for Linked DataMicrotask Crowdsourcing Applications for Linked Data
Microtask Crowdsourcing Applications for Linked Data
 
Mapping Relational Databases to Linked Data
Mapping Relational Databases to Linked DataMapping Relational Databases to Linked Data
Mapping Relational Databases to Linked Data
 
Relational Database to RDF (RDB2RDF)
Relational Database to RDF (RDB2RDF)Relational Database to RDF (RDB2RDF)
Relational Database to RDF (RDB2RDF)
 
Comment manager des geeks - Devoxx 2015
Comment manager des geeks - Devoxx 2015Comment manager des geeks - Devoxx 2015
Comment manager des geeks - Devoxx 2015
 
Annotation Processor, trésor caché de la JVM
Annotation Processor, trésor caché de la JVMAnnotation Processor, trésor caché de la JVM
Annotation Processor, trésor caché de la JVM
 
Querying Linked Data on Android
Querying Linked Data on AndroidQuerying Linked Data on Android
Querying Linked Data on Android
 
Scaling up Linked Data
Scaling up Linked DataScaling up Linked Data
Scaling up Linked Data
 
Interaction with Linked Data
Interaction with Linked DataInteraction with Linked Data
Interaction with Linked Data
 
פתרון חורף 2017 שאלון 806
פתרון חורף 2017 שאלון 806פתרון חורף 2017 שאלון 806
פתרון חורף 2017 שאלון 806
 
Querying Linked Data
Querying Linked DataQuerying Linked Data
Querying Linked Data
 
Java Annotation Processing: A Beginner Walkthrough
Java Annotation Processing: A Beginner WalkthroughJava Annotation Processing: A Beginner Walkthrough
Java Annotation Processing: A Beginner Walkthrough
 

Similar a Conférence sur les annotations Java par Olivier Croisier (Zenika) au Paris JUG

Annotations Java par Olivier Croisier
Annotations Java par Olivier CroisierAnnotations Java par Olivier Croisier
Annotations Java par Olivier CroisierNormandy JUG
 
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdf
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdfdevoxx 2022 - 10 ans de Devoxx FR et de Java.pdf
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdfJean-Michel Doudoux
 
Javaday Paris 2022 - Java en 2022 : profiter de Java 17
Javaday Paris 2022 - Java en 2022 : profiter de Java 17Javaday Paris 2022 - Java en 2022 : profiter de Java 17
Javaday Paris 2022 - Java en 2022 : profiter de Java 17Jean-Michel Doudoux
 
0251-formation-java-programmation-objet.pdf
0251-formation-java-programmation-objet.pdf0251-formation-java-programmation-objet.pdf
0251-formation-java-programmation-objet.pdfOmbotimbe Salifou
 
Voxxeddays lux 2018 apres java 8, java 9 et 10
Voxxeddays lux 2018 apres java 8, java 9 et 10Voxxeddays lux 2018 apres java 8, java 9 et 10
Voxxeddays lux 2018 apres java 8, java 9 et 10Jean-Michel Doudoux
 
Apres java 8, java 9 et 10 - BreizhCamp 2018
Apres java 8, java 9 et 10 - BreizhCamp 2018Apres java 8, java 9 et 10 - BreizhCamp 2018
Apres java 8, java 9 et 10 - BreizhCamp 2018Jean-Michel Doudoux
 
.Net pour le développeur Java - une source d'inspiration?
.Net pour le développeur Java - une source d'inspiration?.Net pour le développeur Java - une source d'inspiration?
.Net pour le développeur Java - une source d'inspiration?Rui Carvalho
 
Devoxx 2018 Après Java 8, Java 9 et 10
Devoxx 2018 Après Java 8, Java 9 et 10Devoxx 2018 Après Java 8, Java 9 et 10
Devoxx 2018 Après Java 8, Java 9 et 10Jean-Michel Doudoux
 
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018Loic Yon
 
Langage Java et Programmation Orienté Objet
Langage Java et Programmation Orienté ObjetLangage Java et Programmation Orienté Objet
Langage Java et Programmation Orienté ObjetMohammed Jaafar
 
JavaLesBasespourles debutantset pour vous.pdf
JavaLesBasespourles debutantset pour vous.pdfJavaLesBasespourles debutantset pour vous.pdf
JavaLesBasespourles debutantset pour vous.pdfhindguendouz2000
 
Qualité logicielle
Qualité logicielleQualité logicielle
Qualité logiciellecyrilgandon
 
Soda sotm fr-2013_02_24
Soda sotm fr-2013_02_24Soda sotm fr-2013_02_24
Soda sotm fr-2013_02_24quicky_osm
 
Soda sotm fr-2013_02_24
Soda sotm fr-2013_02_24Soda sotm fr-2013_02_24
Soda sotm fr-2013_02_24quicky_osm
 

Similar a Conférence sur les annotations Java par Olivier Croisier (Zenika) au Paris JUG (20)

Annotations Java par Olivier Croisier
Annotations Java par Olivier CroisierAnnotations Java par Olivier Croisier
Annotations Java par Olivier Croisier
 
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdf
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdfdevoxx 2022 - 10 ans de Devoxx FR et de Java.pdf
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdf
 
Javaday Paris 2022 - Java en 2022 : profiter de Java 17
Javaday Paris 2022 - Java en 2022 : profiter de Java 17Javaday Paris 2022 - Java en 2022 : profiter de Java 17
Javaday Paris 2022 - Java en 2022 : profiter de Java 17
 
0251-formation-java-programmation-objet.pdf
0251-formation-java-programmation-objet.pdf0251-formation-java-programmation-objet.pdf
0251-formation-java-programmation-objet.pdf
 
Voxxeddays lux 2018 apres java 8, java 9 et 10
Voxxeddays lux 2018 apres java 8, java 9 et 10Voxxeddays lux 2018 apres java 8, java 9 et 10
Voxxeddays lux 2018 apres java 8, java 9 et 10
 
Nouveautés de java 8
Nouveautés de java 8Nouveautés de java 8
Nouveautés de java 8
 
Apres java 8, java 9 et 10 - BreizhCamp 2018
Apres java 8, java 9 et 10 - BreizhCamp 2018Apres java 8, java 9 et 10 - BreizhCamp 2018
Apres java 8, java 9 et 10 - BreizhCamp 2018
 
.Net pour le développeur Java - une source d'inspiration?
.Net pour le développeur Java - une source d'inspiration?.Net pour le développeur Java - une source d'inspiration?
.Net pour le développeur Java - une source d'inspiration?
 
Devoxx 2018 Après Java 8, Java 9 et 10
Devoxx 2018 Après Java 8, Java 9 et 10Devoxx 2018 Après Java 8, Java 9 et 10
Devoxx 2018 Après Java 8, Java 9 et 10
 
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
 
Javaoop
JavaoopJavaoop
Javaoop
 
Langage Java et Programmation Orienté Objet
Langage Java et Programmation Orienté ObjetLangage Java et Programmation Orienté Objet
Langage Java et Programmation Orienté Objet
 
tp-spring.pdf
tp-spring.pdftp-spring.pdf
tp-spring.pdf
 
tp-spring.pdf
tp-spring.pdftp-spring.pdf
tp-spring.pdf
 
JavaLesBasespourles debutantset pour vous.pdf
JavaLesBasespourles debutantset pour vous.pdfJavaLesBasespourles debutantset pour vous.pdf
JavaLesBasespourles debutantset pour vous.pdf
 
Qualité logicielle
Qualité logicielleQualité logicielle
Qualité logicielle
 
Octo Maven.pdf
Octo Maven.pdfOcto Maven.pdf
Octo Maven.pdf
 
Soda sotm fr-2013_02_24
Soda sotm fr-2013_02_24Soda sotm fr-2013_02_24
Soda sotm fr-2013_02_24
 
Soda sotm fr-2013_02_24
Soda sotm fr-2013_02_24Soda sotm fr-2013_02_24
Soda sotm fr-2013_02_24
 
Programmation Java
Programmation JavaProgrammation Java
Programmation Java
 

Más de Zenika

Datascience & IoT
Datascience & IoTDatascience & IoT
Datascience & IoTZenika
 
Matinale Agile Wake Up #4 : les tests et l'agilité
Matinale Agile Wake Up #4 : les tests et l'agilitéMatinale Agile Wake Up #4 : les tests et l'agilité
Matinale Agile Wake Up #4 : les tests et l'agilitéZenika
 
Agile Wake Up #3 : Lean UX
Agile Wake Up #3 : Lean UXAgile Wake Up #3 : Lean UX
Agile Wake Up #3 : Lean UXZenika
 
Agile Wake Up #3 : La transformation Agile de Kisio Digital
Agile Wake Up #3 : La transformation Agile de Kisio DigitalAgile Wake Up #3 : La transformation Agile de Kisio Digital
Agile Wake Up #3 : La transformation Agile de Kisio DigitalZenika
 
Agile Wake Up #3 : la contractualisation Agile
Agile Wake Up #3 : la contractualisation AgileAgile Wake Up #3 : la contractualisation Agile
Agile Wake Up #3 : la contractualisation AgileZenika
 
Zenika matinale spark-zeppelin_ml
Zenika matinale spark-zeppelin_mlZenika matinale spark-zeppelin_ml
Zenika matinale spark-zeppelin_mlZenika
 
Docker du mythe à la réalité
Docker du mythe à la réalitéDocker du mythe à la réalité
Docker du mythe à la réalitéZenika
 
Motivation 3.0 : sens, autonomie et maîtrise.
Motivation 3.0 : sens, autonomie et maîtrise.Motivation 3.0 : sens, autonomie et maîtrise.
Motivation 3.0 : sens, autonomie et maîtrise.Zenika
 
Matinale React
Matinale ReactMatinale React
Matinale ReactZenika
 
NigthClazz Spark - Machine Learning / Introduction à Spark et Zeppelin
NigthClazz Spark - Machine Learning / Introduction à Spark et ZeppelinNigthClazz Spark - Machine Learning / Introduction à Spark et Zeppelin
NigthClazz Spark - Machine Learning / Introduction à Spark et ZeppelinZenika
 
NightClazz Spark / Machine Learning
NightClazz Spark / Machine LearningNightClazz Spark / Machine Learning
NightClazz Spark / Machine LearningZenika
 
HTTP2 : ce qui va changer par Julien Landuré
HTTP2 : ce qui va changer par Julien LanduréHTTP2 : ce qui va changer par Julien Landuré
HTTP2 : ce qui va changer par Julien LanduréZenika
 
Agile Wake Up #1 du 01/12/2015 : L'agilité au service des projets Orange Fran...
Agile Wake Up #1 du 01/12/2015 : L'agilité au service des projets Orange Fran...Agile Wake Up #1 du 01/12/2015 : L'agilité au service des projets Orange Fran...
Agile Wake Up #1 du 01/12/2015 : L'agilité au service des projets Orange Fran...Zenika
 
Agile Wake Up #1 du 01/12/2015 : Scrum Master's Diary par Arnaud Villenave
Agile Wake Up #1 du 01/12/2015 : Scrum Master's Diary par Arnaud VillenaveAgile Wake Up #1 du 01/12/2015 : Scrum Master's Diary par Arnaud Villenave
Agile Wake Up #1 du 01/12/2015 : Scrum Master's Diary par Arnaud VillenaveZenika
 
Agile Wake Up #1 du 01/12/2015 : L'agilité à grande échelle
Agile Wake Up #1 du 01/12/2015 : L'agilité à grande échelleAgile Wake Up #1 du 01/12/2015 : L'agilité à grande échelle
Agile Wake Up #1 du 01/12/2015 : L'agilité à grande échelleZenika
 
Entreprise libérée : Du mythe à la réalité ?
Entreprise libérée : Du mythe à la réalité ?Entreprise libérée : Du mythe à la réalité ?
Entreprise libérée : Du mythe à la réalité ?Zenika
 
Conference MicroServices101 - 1ere partie
Conference MicroServices101 - 1ere partieConference MicroServices101 - 1ere partie
Conference MicroServices101 - 1ere partieZenika
 
NightClazz Docker Découverte
NightClazz Docker Découverte NightClazz Docker Découverte
NightClazz Docker Découverte Zenika
 
Matinale DevOps / Docker
Matinale DevOps / DockerMatinale DevOps / Docker
Matinale DevOps / DockerZenika
 
NightClazz Java 8 Decouverte
NightClazz Java 8 DecouverteNightClazz Java 8 Decouverte
NightClazz Java 8 DecouverteZenika
 

Más de Zenika (20)

Datascience & IoT
Datascience & IoTDatascience & IoT
Datascience & IoT
 
Matinale Agile Wake Up #4 : les tests et l'agilité
Matinale Agile Wake Up #4 : les tests et l'agilitéMatinale Agile Wake Up #4 : les tests et l'agilité
Matinale Agile Wake Up #4 : les tests et l'agilité
 
Agile Wake Up #3 : Lean UX
Agile Wake Up #3 : Lean UXAgile Wake Up #3 : Lean UX
Agile Wake Up #3 : Lean UX
 
Agile Wake Up #3 : La transformation Agile de Kisio Digital
Agile Wake Up #3 : La transformation Agile de Kisio DigitalAgile Wake Up #3 : La transformation Agile de Kisio Digital
Agile Wake Up #3 : La transformation Agile de Kisio Digital
 
Agile Wake Up #3 : la contractualisation Agile
Agile Wake Up #3 : la contractualisation AgileAgile Wake Up #3 : la contractualisation Agile
Agile Wake Up #3 : la contractualisation Agile
 
Zenika matinale spark-zeppelin_ml
Zenika matinale spark-zeppelin_mlZenika matinale spark-zeppelin_ml
Zenika matinale spark-zeppelin_ml
 
Docker du mythe à la réalité
Docker du mythe à la réalitéDocker du mythe à la réalité
Docker du mythe à la réalité
 
Motivation 3.0 : sens, autonomie et maîtrise.
Motivation 3.0 : sens, autonomie et maîtrise.Motivation 3.0 : sens, autonomie et maîtrise.
Motivation 3.0 : sens, autonomie et maîtrise.
 
Matinale React
Matinale ReactMatinale React
Matinale React
 
NigthClazz Spark - Machine Learning / Introduction à Spark et Zeppelin
NigthClazz Spark - Machine Learning / Introduction à Spark et ZeppelinNigthClazz Spark - Machine Learning / Introduction à Spark et Zeppelin
NigthClazz Spark - Machine Learning / Introduction à Spark et Zeppelin
 
NightClazz Spark / Machine Learning
NightClazz Spark / Machine LearningNightClazz Spark / Machine Learning
NightClazz Spark / Machine Learning
 
HTTP2 : ce qui va changer par Julien Landuré
HTTP2 : ce qui va changer par Julien LanduréHTTP2 : ce qui va changer par Julien Landuré
HTTP2 : ce qui va changer par Julien Landuré
 
Agile Wake Up #1 du 01/12/2015 : L'agilité au service des projets Orange Fran...
Agile Wake Up #1 du 01/12/2015 : L'agilité au service des projets Orange Fran...Agile Wake Up #1 du 01/12/2015 : L'agilité au service des projets Orange Fran...
Agile Wake Up #1 du 01/12/2015 : L'agilité au service des projets Orange Fran...
 
Agile Wake Up #1 du 01/12/2015 : Scrum Master's Diary par Arnaud Villenave
Agile Wake Up #1 du 01/12/2015 : Scrum Master's Diary par Arnaud VillenaveAgile Wake Up #1 du 01/12/2015 : Scrum Master's Diary par Arnaud Villenave
Agile Wake Up #1 du 01/12/2015 : Scrum Master's Diary par Arnaud Villenave
 
Agile Wake Up #1 du 01/12/2015 : L'agilité à grande échelle
Agile Wake Up #1 du 01/12/2015 : L'agilité à grande échelleAgile Wake Up #1 du 01/12/2015 : L'agilité à grande échelle
Agile Wake Up #1 du 01/12/2015 : L'agilité à grande échelle
 
Entreprise libérée : Du mythe à la réalité ?
Entreprise libérée : Du mythe à la réalité ?Entreprise libérée : Du mythe à la réalité ?
Entreprise libérée : Du mythe à la réalité ?
 
Conference MicroServices101 - 1ere partie
Conference MicroServices101 - 1ere partieConference MicroServices101 - 1ere partie
Conference MicroServices101 - 1ere partie
 
NightClazz Docker Découverte
NightClazz Docker Découverte NightClazz Docker Découverte
NightClazz Docker Découverte
 
Matinale DevOps / Docker
Matinale DevOps / DockerMatinale DevOps / Docker
Matinale DevOps / Docker
 
NightClazz Java 8 Decouverte
NightClazz Java 8 DecouverteNightClazz Java 8 Decouverte
NightClazz Java 8 Decouverte
 

Conférence sur les annotations Java par Olivier Croisier (Zenika) au Paris JUG

  • 3. Les Annotations Java Enfin  expliquées  simplement ! ©Zenika 3
  • 4. Olivier Croisier J'aime  • Consultant Zenika tellement ses  quizz Java ! • Certifié Java 5.0 (100%) • Certifié Spring Framework • Formateur certifié JavaSpecialist (javaspecialists.eu) • Formateur certifié Terracotta • Blog : The Coder's Breakfast ( thecodersbreakfast.net ) • Twitter : @OlivierCroisier (Illustration. Effet dramatisé) ©Zenika 4
  • 5. Plan • Présentation • Annotations, mode d'emploi • Annotations personnalisées • Outillage compile-time • Outillage runtime • Injection d'annotations • Conclusion ©Zenika 5
  • 6. Plan • Présentation • Historique • Où trouver des annotations ? • Annotations, mode d'emploi • Annotations personnalisées • Outillage compile-time • Outillage runtime • Injection d'annotations • Conclusion ©Zenika 6
  • 7. Présentation Historique • Java a toujours proposé une forme ou une autre de méta- programmation • Dès l'origine, l'outil "javadoc" permettait d'exploiter automatiquement des méta-données à but documentaire /** /** ** Méthode inutile Méthode inutile ** @param param Un paramètre (non utilisé) @param param Un paramètre (non utilisé) ** @return Une valeur fixe :: "foo" @return Une valeur fixe "foo" ** @throws Exception N'arrive jamais (promis!) @throws Exception N'arrive jamais (promis!) */*/ public String foo(String param) throws Exception {{ public String foo(String param) throws Exception return "foo"; return "foo"; }} ©Zenika 7
  • 8. Présentation Historique • Ce système était flexible et a rapidement été utilisé / détourné pour générer d'autres artefacts : fichiers de configuration, classes annexes... • Voir le projet XDoclet (xdoclet.sourceforfge.net) /** /** ** @ejb.bean @ejb.bean ** name="bank/Account" name="bank/Account" ** type="CMP" type="CMP" ** jndi-name="ejb/bank/Account" jndi-name="ejb/bank/Account" ** local-jndi-name="ejb/bank/LocalAccount" local-jndi-name="ejb/bank/LocalAccount" ** primkey-field="id" primkey-field="id" ** @ejb.transaction @ejb.transaction ** type="Required" type="Required" ** @ejb.interface @ejb.interface ** remote-class="test.interfaces.Account" remote-class="test.interfaces.Account" */ */ ©Zenika 8
  • 9. Présentation Historique • Reconnaissant le besoin d'un système de méta-programmation plus robuste et plus flexible, Java 5.0 introduit les Annotations • Elles remplacent avantageusement les doclets dans tous les domaines – sauf bien sûr pour la génération de la Javadoc ! public class PojoAnnotation extends Superclass {{ public class PojoAnnotation extends Superclass @Override @Override public void overridenMethod() {{ public void overridenMethod() super.overridenMethod(); super.overridenMethod(); }} @Deprecated @Deprecated public void oldMethod(){ public void oldMethod(){ }} }} ©Zenika 9
  • 10. Présentation Où trouver des annotations ? • Java SE propose assez peu d'annotations en standard • @Deprecated, @Override, @SuppressWarnings • 4 méta-annotations dans java.lang.annotation • Celles définies par JAXB et Commons Annotations @ @ • Java EE en fournit une quantité impressionnante • Pour les EJB 3, les Servlets 3, CDI, JSF 2, JPA... @ • Les frameworks modernes en tirent également parti • Spring, Hibernate, CXF, Stripes... • Développez les vôtres ! ©Zenika 10
  • 11. Plan • Présentation • Annotations, mode d'emploi • Elements annotables • Annoter une classe, une méthode ou un champ • Annoter un package • Paramètres d'annotations • Restrictions et astuces • Annotations personnalisées • Outillage compile-time • Outillage runtime • Injection d'annotations • Conclusion ©Zenika 11
  • 12. Annotations, mode d'emploi Elements annotables • Les annotations peuvent être apposées sur les éléments suivants : • Les classes, interfaces et enums • Les propriétés de classes • Les constructeurs et méthodes • Les paramètres des constructeurs et méthodes • Les variables locales • … et d'autres éléments encore grâce à la JSR 308 (Java 7 8) • Mais aussi sur... • Les packages • Les annotations elles-mêmes (méta-annotations) ! ©Zenika 12
  • 13. Annotations, mode d'emploi Annoter une classe, méthode ou champ @Deprecated @Deprecated public class Pojo {{ public class Pojo @Deprecated @Deprecated private int foo; private int foo; @Deprecated @Deprecated public Pojo() {{ public Pojo() @Deprecated @Deprecated int localVar ==0; int localVar 0; }} @Deprecated @Deprecated public int getFoo() {{ public intfoo; return getFoo() return foo; }} public void setFoo(@Deprecated int foo) {{ public void setFoo(@Deprecated int foo) this.foo ==foo; this.foo foo; }} }} ©Zenika 13
  • 14. Annotations, mode d'emploi Annoter un package • Comment annoter un package ? • La déclaration d'un package est présente dans toutes les classes appartenant à ce package. Impossible d'y placer une annotation : risque de conflit ou d'information incomplète ! @Foo @Foo package com.zenika.presentation.annotations; package com.zenika.presentation.annotations; public class ClassA {} public class ClassA {} @Bar @Bar package com.zenika.presentation.annotations; package com.zenika.presentation.annotations; public class ClassB {} public class ClassB {} ©Zenika 14
  • 15. Annotations, mode d'emploi Annoter un package • Solution : pour annoter un package, il faut créer un fichier spécial nommé package-info.java • Il contient uniquement la déclaration du package, accompagné de sa javadoc et de ses annotations /** /** ** Ce package contient le code source de Ce package contient le code source de ** la présentation sur les annotations. la présentation sur les annotations. */ */ @Foo @Foo @Bar @Bar package com.zenika.presentation.annotations; package com.zenika.presentation.annotations; ©Zenika 15
  • 16. Annotations, mode d'emploi Paramètres d'annotations • Les annotations peuvent prendre des paramètres • Ils peuvent être obligatoires ou facultatifs (ils prennent alors la valeur par défaut spécifiée par le développeur de l'annotation) • Les paramètres se précisent entre parenthèses, à la suite de l'annotation ; leur ordre n'est pas important @MyAnnotation( param1=value1, param2=value2... )) @MyAnnotation( param1=value1, param2=value2... • Si l'annotation ne prend qu'un paramètre, il est souvent possible d'utiliser une notation raccourcie @MyAnnotation( value )) @MyAnnotation( value ©Zenika 16
  • 17. Annotations, mode d'emploi Paramètres d'annotations @WebInitParam( name="foo", value="bar" )) @WebInitParam( name="foo", value="bar" ©Zenika 17
  • 18. Annotations, mode d'emploi Restrictions et astuces • Il est interdit d'annoter plusieurs fois un élément avec la même annotation. Pour contourner le problème, on peut recourir à des annotations "wrapper" @SecondaryTables({ @SecondaryTables({ @SecondaryTable(name="city"), @SecondaryTable(name="city"), @SecondaryTable(name="country") @SecondaryTable(name="country") }) }) public class Address public class Address {...} {...} • Il est possible de séparer l'@ du nom de l'annotation ! @@ /** Javadoc */ /** Javadoc */ Deprecated Deprecated ©Zenika 18
  • 19. Annotations, mode d'emploi Restrictions et astuces • Pour les paramètres : • Les valeurs des paramètres doivent être des "compile-time constants"... @MyAnnotation(answer == (true!=false) ?? 42 :: 0) @MyAnnotation(answer (true!=false) 42 0) • … mais ne peuvent pas être null (Et personne ne sait pourquoi !) @MyAnnotation(param == null) @MyAnnotation(param null) ©Zenika 19
  • 20. Plan • Présentation • Annotations, mode d'emploi • Annotations personnalisées • Use-cases • Méta-annotations • Paramètres d'annotations • Outillage compile-time • Outillage runtime • Injection d'annotations • Conclusion ©Zenika 20
  • 21. Annotations personnalisées A quoi ça sert ? • Pourquoi développer des annotations personnalisées ? • Pour remplacer / compléter des fichiers de configuration XML • Pour simplifier ou générifier une portion de code en recourant à la méta-programmation • Pour appliquer des règles de compilation supplémentaires, grâce aux Annotation Processors • … parce que c'est fun ! ©Zenika 21
  • 22. Annotations personnalisées Syntaxe • Une annotation se déclare comme un type spécial d'interface • Elle sera compilée sous la forme d'une interface héritant de java.lang.annotation.Annotation public @interface MyAnnotation {{ public @interface MyAnnotation }} • Il est ensuite possible de compléter l'annotation avec : • Des paramètres •Pour véhiculer des données supplémentaires • Des méta-annotations •Pour spécifier les conditions d'utilisation de l'annotation ©Zenika 22
  • 23. Annotation personnalisées Paramètres d'annotations • Chaque paramètre se déclare sous la forme d'une méthode (non générique, sans paramètres et sans exceptions) • Il peut posséder une valeur par défaut (compile-time constant), déclarée grâce au mot-clé "default" ; il est alors optionnel. public @interface MyAnnotation {{ public @interface MyAnnotation String message(); String message(); int answer() default 42; int answer() default 42; }} @MyAnnotation( message="Hello World" )) @MyAnnotation( message="Hello World" @MyAnnotation( message="Hello World", answer == 00 )) @MyAnnotation( message="Hello World", answer ©Zenika 23
  • 24. Annotation personnalisées Paramètres d'annotations • Si l'annotation ne possède qu'un seul paramètre nommé "value", il est possible d'utiliser une syntaxe raccourcie public @interface MyAnnotation {{ public @interface MyAnnotation String value(); String value(); }} @MyAnnotation( "Hello World" )) @MyAnnotation( "Hello World" @MyAnnotation( value == "Hello World" )) @MyAnnotation( value "Hello World" ©Zenika 24
  • 25. Annotation personnalisées Paramètres d'annotations • Comme dans toute interface, il est possible de définir des classes, interfaces ou enums internes public @interface MyAnnotation {{ public @interface MyAnnotation int defaultAnswer == 42; int defaultAnswer 42; int answer() default defaultAnswer; int answer() default defaultAnswer; enum Season {SPRING, SUMMER, FALL, WINTER}; enum Season {SPRING, SUMMER, FALL, WINTER}; Season season(); Season season(); }} @MyAnnotation( season == MyAnnotation.Season.WINTER )) @MyAnnotation( season MyAnnotation.Season.WINTER ©Zenika 25
  • 26. Annotation personnalisées Les Méta-Annotations : @Target • La méta-annotation @Target indique sur quels éléments de code l'annotation peut être apposée : @Target( ElementType[] )) @Target( ElementType[] public @interface MyAnnotation {{ public @interface MyAnnotation }} • Exemple : @Target( {ElementType.TYPE, ElementType.METHOD} )) @Target( {ElementType.TYPE, ElementType.METHOD} public @interface MyAnnotation {{ public @interface MyAnnotation }} ©Zenika 26
  • 27. Annotation personnalisées Les Méta-Annotations : @Target • Valeurs possibles pour l'enum ElementType : • TYPE • CONSTRUCTOR • FIELD • METHOD • PARAMETER • LOCAL_VARIABLE • ANNOTATION_TYPE (méta-annotation) • PACKAGE • TYPE_PARAMETER et TYPE_USE (JSR 308, Java 7 8) Ex: @English String @NonEmpty [] • Si le paramètre n'est pas spécifié, l'annotation peut être utilisée partout (Ex : @Deprecated) ©Zenika 27
  • 28. Annotation personnalisées Les Méta-Annotations : @Retention • La méta-annotation @Retention indique la durée de vie de l'annotation @Retention( RetentionPolicy )) @Retention( RetentionPolicy public @interface MyAnnotation {{ public @interface MyAnnotation }} • Exemple @Retention( RetentionPolicy.RUNTIME )) @Retention( RetentionPolicy.RUNTIME public @interface MyAnnotation {{ public @interface MyAnnotation }} ©Zenika 28
  • 29. Annotation personnalisées Les Méta-Annotations : @Retention • Valeurs possibles pour l'enum RetentionPolicy : • SOURCE • CLASS (par défaut) • RUNTIME compilation class loading SOURCE CLASS RUNTIME ©Zenika 29
  • 30. Annotation personnalisées Les Méta-Annotations : @Inherited • La méta-annotation @Inherited indique que l'annotation est héritée par les classes filles de la classe annotée @Inherited @Inherited public @interface MyAnnotation {{ public @interface MyAnnotation }} • Restrictions • Seules les annotations portées sur les classes sont héritées • Les annotations apposées sur une interface ne sont pas héritées par les classes implémentant cette interface ; idem pour les packages. ©Zenika 30
  • 31. Annotation personnalisées Les Méta-Annotations : @Documented • La méta-annotation @Documented indique que l'annotation doit apparaître dans la javadoc @Documented @Documented public @interface MyAnnotation {{ public @interface MyAnnotation }} ©Zenika 31
  • 32. Plan • Présentation • Anatomie • Mode d'emploi • Annotations personnalisées • Outillage compile-time • Historique et use-cases • Processus de compilation • Anatomie d'un processeur • Limitations • Outillage runtime • Injection d'annotations • Conclusion ©Zenika 32
  • 33. Outillage compile-time Historique et use-cases Historique • Java 5.0 : APT (Annotation Processing Tool) • Devait être lancé en plus du compilateur javac • Java 6.0 : Pluggable Annotation Processors • Intégrés au processus de compilation standard • Paramètre -processor ou utilisation du SPI (Service Provider Interface) Pour plus d'informations sur le SPI, voir : • Un article sur The Coder's Breakfast • La Javadoc de java.util.ServiceLoader ©Zenika 33
  • 34. Outillage compile-time Historique et use-cases Use-cases • Génération de ressources : "XDoclet ++" • Fichiers de configuration • Classes annexes •Ex: Proxies, PropertyEditors... • Documentation •Ex: Matrice des rôles JavaEE, cartographie d'IOC... • Amélioration du compilateur • Vérification de normes de codage •Ex: Les classes "modèle" doivent être Serializable... • Messages d'alerte ou d'erreur supplémentaires ©Zenika 34
  • 35. Outillage compile-time Historique et use-cases Mention spéciale : Lombok (projectlombok.org) • Améliore "magiquement" les classes •Génère les getters/setters, equals/hashCode, toString • Viole la règle de non-modification des ressources existantes • Dépend des implémentations internes des compilateurs pour manipuler les AST des classes •com.sun.tools.javac.* •org.eclipse.jdt.internal.compiler.* • Danger : la compilation de votre projet dépend désormais du support de votre compilateur cible par Lombok. Peser le rapport gain / risques ! •Votre IDE propose également ces fonctionnalités ! ©Zenika 35
  • 36. Outillage compile-time Processus de compilation 1. Le compilateur découvre les processeurs d'annotations •Paramètre -processor sur la ligne de commande •ou via le Service Provider Interface (SPI) 2. Un round de compilation est lancé •Le compilateur et les processeurs s'exécutent •Si de nouvelles ressources sont créées lors de ce round, un nouveau round est lancé ©Zenika 36
  • 37. Outillage compile-time Anatomie d'un Processeur • Un processeur est une classe implémentant l'interface javax.annotation.processing.Processor • Généralement, on sous-classe AbstractProcessor • L'annotation @SupportedAnnotationTypes permet d'indiquer quelles annotations le processeur sait traiter • La méthode init() permet d'initialiser le processeur • La méthode principale process() reçoit un paramètre de type RoundEnvironment représentant l'environnement de compilation. Elle renvoie un booléen indiquant si l'annotation est définitivement "consommée" par ce processeur ©Zenika 37
  • 38. Outillage compile-time Anatomie d'un Processeur • Des utilitaires sont accessibles via la propriété processingEnv fournie par AbstractProcessor : • Types et Elements, permettant d'introspecter le code • Messager, pour lever des erreurs de compilation et afficher des messages dans la console • Filer, autorisant la création de nouvelles ressources (classes, fichiers de configuration...) Types Types types types == processingEnv.getTypeUtils(); processingEnv.getTypeUtils(); Elements Elements elts elts == processingEnv.getElementUtils(); processingEnv.getElementUtils(); Messager Messager messager messager == processingEnv.getMessager(); processingEnv.getMessager(); Filer Filer filer filer == processingEnv.getFiler(); processingEnv.getFiler(); ©Zenika 38
  • 39. Outillage compile-time Anatomie d'un Processeur @SupportedAnnotationTypes("com.zenika.*") @SupportedAnnotationTypes("com.zenika.*") public class MyProcessor extends AbstractProcessor {{ public class MyProcessor extends AbstractProcessor Types types; Types types; Elements elements; Elements elements; Messager messager; Messager messager; Filer filer; Filer filer; public void init(ProcessingEnvironment processingEnv) {{ public void init(ProcessingEnvironment processingEnv) super.init(processingEnv); super.init(processingEnv); types types == processingEnv.getTypeUtils(); processingEnv.getTypeUtils(); elements == processingEnv.getElementUtils(); elements processingEnv.getElementUtils(); messager == processingEnv.getMessager(); messager = processingEnv.getFiler(); processingEnv.getMessager(); filer filer = processingEnv.getFiler(); }} public boolean process( public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {annotations, Set<? extends TypeElement> RoundEnvironment roundEnv) { // TODO }} // TODO }} ©Zenika 39
  • 40. Outillage compile-time Anatomie d'un Processeur public boolean process( public boolean process( Set<? extends TypeElement> annotations, Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {{ RoundEnvironment roundEnv) // Pour chaque annotation traitée... // Pour chaque annotation traitée... for (TypeElement annotation :: annotations) {{ for (TypeElement annotation annotations) // Trouver les éléments portant cette annotation // Trouver les éléments portant cette annotation for (Element ee :: for (Element roundEnv.getElementsAnnotatedWith(annotation)) {{ roundEnv.getElementsAnnotatedWith(annotation)) messager.printMessage( messager.printMessage( Diagnostic.Kind.NOTE, Diagnostic.Kind.NOTE, e.getSimpleName()); e.getSimpleName()); }} }} return false; return false; }} ©Zenika 40
  • 41. Outillage compile-time Limitations • Développer un processeur est complexe ! • Les Types et les Elements offrent deux vues différentes sur le code compilé •Les Elements représentent l'AST brut du code •Les Types offrent une interface davantage typée "java" •Il existe des ponts entre ces deux univers • Le pattern Visiteur est beaucoup utilisé • Un processeur ne peut pas modifier du code existant ! • Quelques bugs encore, et un faible support dans les IDE ©Zenika 41
  • 42. Outillage compile-time Démos Démos • ListingProcessor •MessageHolderProcessor •SerializableClassesProcessor ©Zenika 42
  • 43. Plan • Présentation • Annotations, mode d'emploi • Annotations personnalisées • Outillage compile-time • Outillage runtime • Use-cases • Récupération des paramètres • Une fois les annotations récupérées... • Injection d'annotations • Conclusion ©Zenika 43
  • 44. Outillage runtime Use-cases • Au runtime, il est possible d'utiliser la Réflexion pour découvrir les annotations présentes sur les classes, champs, méthodes et paramètres de méthodes. • Uniquement si @Retention(RetentionPolicy.RUNTIME) • Use-cases : • Mapping Java ↔ ? • Programmation orientée POJO • Configuration de containers / frameworks • Exemples : • Hibernate, Apache CXF, XStream... • Spring, Guice, Java EE 5/6 (CDI, EJB 3.0, Servlets 3.0...) ©Zenika 44
  • 45. Outillage runtime Récupération des annotations • Les classes Package, Class, Constructor, Field et Method implémentent l'interface AnnotatedElement : public interface AnnotatedElement {{ public interface AnnotatedElement Annotation[] getAnnotations(); Annotation[] getAnnotations(); Annotation[] getDeclaredAnnotations(); Annotation[] getDeclaredAnnotations(); boolean isAnnotationPresent(Class annotationClass); boolean isAnnotationPresent(Class annotationClass); Annotation getAnnotation(Class annotationClass); Annotation getAnnotation(Class annotationClass); }} • getAnnotations() renvoie toutes les annotations applicables à l'élément, y compris les annotations héritées • getDeclaredAnnotations() ne renvoie que les annotations directement apposées sur l'élément ©Zenika 45
  • 46. Outillage runtime Récupération des annotations • Exemple : lecture des annotations d'une classe et de celles de son package // Annotations sur la classe // Annotations sur la classe Annotation[] clsAnnots == Pojo.class.getAnnotations(); Annotation[] clsAnnots Pojo.class.getAnnotations(); for (Annotation annot :: clsAnnots) {{ for (Annotation annot clsAnnots) System.out.println(annot); System.out.println(annot); }} // Annotations sur le package // Annotations sur le package Package pkg == Pojo.class.getPackage(); Package pkg Pojo.class.getPackage(); Annotation[] pkgAnnots == pkg.getDeclaredAnnotations(); Annotation[] pkgAnnots pkg.getDeclaredAnnotations(); for (Annotation annot :: pkgAnnots) {{ for (Annotation annot pkgAnnots) System.out.println(annot); System.out.println(annot); }} ©Zenika 46
  • 47. Outillage runtime Récupération des annotations • Les classes Constructor et Method permettent également de récupérer les annotations présentes sur leurs paramètres • Annotation[][] getParameterAnnotations() • Renvoie un tableau d'annotations par paramètre, dans l'ordre de leur déclaration dans la signature de la méthode public void printParamAnnots(Method method) {{ public void printParamAnnots(Method method) Annotation[][] paramAnnots == Annotation[][] paramAnnots method.getParameterAnnotations(); method.getParameterAnnotations(); for (Annotation[] annots :: paramAnnots) {{ for (Annotation[] annots paramAnnots) System.out.println(Arrays.toString(annots)); System.out.println(Arrays.toString(annots)); }} }} ©Zenika 47
  • 48. Outillage runtime Une fois les annotations récupérées... • Que peut-on faire avec les annotations récupérées par réflexion ? • On peut découvrir leur type dynamiquement Class<? extends Annotation> annotationType() • On peut lire leurs paramètres (cast nécessaire) Annotation annot == …… ;; Annotation annot // Détermination du type réel de l'annotation // Détermination du type réel de l'annotation Class<? extends Annotation> annotClass == Class<? extends Annotation> annotClass myAnnotation.annotationType(); myAnnotation.annotationType(); // Affichage du message de MyAnnotation // Affichage du message de MyAnnotation if (annot instanceof MyAnnotation) {{ if (annot instanceof MyAnnotation) MyAnnotation myAnnot == (MyAnnotation) annot; MyAnnotation myAnnot (MyAnnotation) annot; System.out.println(myAnnot.message()); System.out.println(myAnnot.message()); }} ©Zenika 48
  • 49. Outillage runtime Démos Démos • Démonstration • Exemple : CSVReader ©Zenika 49
  • 50. Plan • Présentation • Mode d'emploi • Annotations personnalisées • Outillage compile-time • Outillage runtime • Injection d'annotations • Au coeur de la classe Class • Instancier dynamiquement une annotation • Injection dans une classe • Injection sur une méthode ou un champ • Conclusion ©Zenika 50
  • 51. Injection d'annotations Au coeur de la classe Class • Dans la classe Class, les annotations sont représentées sous la forme de Maps : private transient Map<Class, Annotation> annotations; private transient Map<Class, Annotation> annotations; private transient Map<Class, Annotation> declaredAnnotations; private transient Map<Class, Annotation> declaredAnnotations; • Ces maps sont initialisées lors du premier appel à getAnnotations() ou getDeclaredAnnotations() • L'initialisation est réalisée en décodant le byte[] renvoyé par la méthode native getRawAnnotations() • En modifiant ces maps par Réflexion, il est possible d'injecter arbitrairement des annotations sur une Classe au runtime ! ©Zenika 51
  • 52. Injection d'annotations Instancier une annotation • Pour obtenir une instance de l'annotation à injecter, il suffit d'instancier une classe anonyme implémentant son "interface" MyAnnotation myAnnotation == new MyAnnotation() {{ MyAnnotation myAnnotation new MyAnnotation() @Override @Override public String message() {{ public String message() return MyAnnotation.defaultMessage; }} return MyAnnotation.defaultMessage; @Override @Override public int answer() {{ public intMyAnnotation.defaultAnswer; answer() return MyAnnotation.defaultAnswer; }} return @Override @Override public Class<? extends Annotation> annotationType() {{ public Class<? extends Annotation> annotationType() return MyAnnotation.class; }} return MyAnnotation.class; }; }; ©Zenika 52
  • 53. Injection d'annotations Instancier une annotation • Attention, les annotations créées programmatiquement doivent implémenter les méthodes equals() et hashCode() en respectant le contrat décrit dans la Javadoc. • hashCode() : • "The hash code of an annotation is the sum of the hash codes of its members (including those with default values)" • equals() : • "Returns true if the specified object is an instance of the same annotation type as this instance, all of whose members are equal to the corresponding member of this annotation" ©Zenika 53
  • 54. Injection d'annotations Injection sur une Classe • Il ne reste plus qu'à utiliser la Réflexion pour injecter notre annotation dans la classe cible public static void injectClass public statictargetClass, Annotation annotation) { void injectClass (Class<?> targetClass, Annotation annotation) { (Class<?> // Initialisation des maps d'annotations // Initialisation des maps d'annotations targetClass.getAnnotations(); targetClass.getAnnotations(); // Récupération de la map interne des annotations // Récupération de la map interne des annotations Field mapRef == Class.class.getDeclaredField("annotations"); Field mapRef Class.class.getDeclaredField("annotations"); mapRef.setAccessible(true); mapRef.setAccessible(true); // Modification de la map des annotations Map<Class, Annotation> map des=annotations // Modification de la annots Map<Class, Annotation> annots = (Map<Class, Annotation>) mapRef.get(targetClass); if (annots==null Annotation>) mapRef.get(targetClass); (Map<Class, || annots.isEmpty()) { if annots = new HashMap<Class, Annotation>(); (annots==null || annots.isEmpty()) { }} annots = new HashMap<Class, Annotation>(); pojoAnnotations.put(annotation.annotationType(), annotation); pojoAnnotations.put(annotation.annotationType(), annotation); mapRef.set(targetClass, pojoAnnotations); }} mapRef.set(targetClass, pojoAnnotations); ©Zenika 54
  • 55. Injection d'annotations Injection sur une Méthode ou un Champ • L'injection d'annotations sur les classes Constructor, Field et Method est plus problématique • Au sein de la classe Class, les méthodes getConstructor(), getField(), ou getMethod() renvoient des copies des objets correspondants Method m1 == Pojo.class.getDeclaredMethod("foo", null); Method m1 Pojo.class.getDeclaredMethod("foo", null); Method m2 == Pojo.class.getDeclaredMethod("foo", null); Method m2 Pojo.class.getDeclaredMethod("foo", null); System.out.println(m1==m2); // false System.out.println(m1==m2); // false • Ces copies sont initialisées directement à partir du bytecode de la classe, pas à partir d'une instance prééxistante • Les modifications apportées aux maps d'annotations sur une instance sont donc strictement locales à cette instance ©Zenika 55
  • 56. Injection d'annotations Injection sur une Méthode ou un Champ • Alors, comment faire ? • AOP pour intercepter les méthodes getConstructor(), getMethod(), getField() ? • Modifier directement la portion de bytecode correspondant à ces objets ? • Si vous trouvez une solution, je suis preneur ! ©Zenika 56
  • 57. Injection d'annotations Use-cases • Use-cases • Les annotations @Inherited posées sur les interfaces ne sont pas héritées par les classes implémentant ces interfaces. Il est possible d'y remédier en réinjectant manuellement ces annotations dans les classes. Mais attention aux conflits ! • Idem pour les annotations posées sur les packages • … d'autres idées ? ©Zenika 57
  • 58. Injection d'annotations Démos Démos • Injection dans une classe • Injection dans un champ ©Zenika 58
  • 59. Plan • Présentation • Mode d'emploi • Annotations personnalisées • Outillage compile-time • Outillage runtime • Injection d'annotations • Conclusion ©Zenika 59
  • 60. Conclusion • Les doclets ont ouvert la voie à la méta-programmation ; Java 5.0 a standardisé et démocratisé les annotations • Tous les frameworks modernes utilisent les annotations • Elles complètent parfaitement les fichiers de configuration XML • Il est facile de développer des annotations personnalisées • Java fournit des outils pour les exploiter lors de la compilation et au runtime • Mais attention à la complexité ! ©Zenika 60
  • 61. ? Conclusion Questions / Réponses ©Zenika 61
  • 62. Références • Annotation processors • La documentation du SDK et la JLS • "Enforcing design rules with Pluggable Annotation Processors" sur http://thecodersbreakfast.net • La newsletter Javaspecialists (http://javaspecialists.eu) • JSR 308 et le framework Checkers • http://types.cs.washington.edu/jsr308/ • Lombok • http://projectlombok.org/ ©Zenika 62