Introspection reflection

19
Eric TOGUEM, CIO AByster ( www.abyster.com ) INTROSPECTION / REFLECTION EN JAVA 1

Transcript of Introspection reflection

Page 1: Introspection reflection

1

Eric TOGUEM, CIO AByster (www.abyster.com)

INTROSPECTION / REFLECTION EN JAVA

Page 2: Introspection reflection

2 MOTIVATIONS

Besoin de:

Déterminer une caractéristique d'un objet de façon dynamique,

Pouvoir agir de façon générique sur un objet,

Pour cela, il est nécessaire de :

Disposer d'informations sur les méta données des classes

Pouvoir agir sur un objet en ne connaissant pas le champs ou la méthode concernés au moment de la compilation

Page 3: Introspection reflection

3 LE BYTE CODE

Ne se limite pas à de simples instructions exécutables.

Contient de nombreuses informations plus proches du code source du fichier .class : les méta données

Classe parente,

Interface implémentée,

Champs,

Méthodes

Page 4: Introspection reflection

4CONSÉQUENCES AU

NIVEAU DE L'EXÉCUTION

Le premier domaine d'application est l'exécution,

Exemple:

Vous utilisez une bibliothèque pour écrire un petit programme que vous compilez

Une nouvelle version de la bibliothèque devient disponible. Vous remplacez le jar et relancez votre programme Java.lang.NoSuchMethodError At

MonProg.main(MonProg.java:36)

Page 5: Introspection reflection

5 L'UTILITAIRE JAVAP

Décompilateur élémentaire.

Classe parente,

Interface implémentée,

Champs,

Méthodes

Il est présent dans le répertoire jdk\bin et sa syntaxe de base est la suivante

javap monPaquetage.NomClasse

Page 6: Introspection reflection

6CAS D’UTILISATIONS DE

L’API REFLECTION

Introspection = découverte des caractéristiques d'une classe (classe mère, champs, méthodes, ...),

Instancier des classes de manière dynamique, en agissant sur ses champs, en appelant ses méthodes ...

Écriture d'un générateur de code générique pour un ensemble de classe.

Processus de sérialisation d'un bean Java ou dans la génération du code de création d'un table en base de données pour la persistance de la classe cible.

Pour tout outil devant faire abstraction des spécificités d'une application en proposant un service générique pour n'importe quelle classe.

Page 7: Introspection reflection

7

PAQUETAGE JAVA.LANG.REFLECT:  LA

CLASSE CLASS

Les instances sont des classes ou des interfaces,

Elle est indispensable pour pouvoir manipuler des méta données

Exemple

public class Exemple {

public Exemple() { }

public String getNom(Object o) {

Class c = o.getClass();

return c.getName();

}

}

Page 8: Introspection reflection

8

PAQUETAGE JAVA.LANG.REFLECT:  LES MÉTHODES DE LA CLASSE

CLASS

java.lang.reflect.Field getField(String name),

java.lang.reflect.Field[] getFields(),

java.lang.reflect.Method getMethod(String name, Class[] parameterTypes),

java.lang.reflect.Method[] getMethods(),

java.lang.reflect.Constructor getConstructor(Class[] parameterTypes),

java.lang.reflect.Constructor[] getConstructors(),

Class[] getInterfaces(),

Class getSuperclass(),

java.lang.Package getPackage(),

Page 9: Introspection reflection

9

PAQUETAGE JAVA.LANG.REFLECT:  LA

CLASSE FIELD

Contient les informations sur un champ,

Quelques méthodes:

String getName()

Class getType()

int getModifier()

Page 10: Introspection reflection

10

PAQUETAGE JAVA.LANG.REFLECT:  LA

CLASSE MODIFIER

Permet d’interpréter le modificateur renvoyé par le field,

Quelques unes de ses méthodes

boolean static isFinal(int mod)

boolean static isPublic(int mod)

boolean static isStatic(int mod)

Page 11: Introspection reflection

11

PAQUETAGE JAVA.LANG.REFLECT:  LA

CLASSE METHOD

Contient les informations sur une méthodes,

Quelques méthodes:

Class[] getExceptionTypes()

String getName()

Class getReturnType()

Class[] getParameterTypes()

int getModifiers()

Dans le cas d’un type primitif, le wrapper est utilisé,

Page 12: Introspection reflection

12

PAQUETAGE JAVA.LANG.REFLECT:  LA

CLASSE CONSTRUCTOR

Contient les informations sur un constructeur,

Quelques méthodes:

Class[] getExceptionTypes()

String getName()

Class[] getParameterTypes()

int getModifiers()

Page 13: Introspection reflection

13

UTILISATION DE LA RÉFLEXIVITÉ: EDITION ET

CONSULTATION D'UN CHAMP

void changeValeur(Object o, String nomChamp, Object val) throws Exception {

Field f = o.getClass().getField(nomChamp); f.set(o,val);

}

void afficheValeur(Object o, String nomChamp) throws Exception {

Field f = o.getClass().getField(nomChamp); System.out.println(f.get(o));

}

Page 14: Introspection reflection

14

UTILISATION DE LA RÉFLEXIVITÉ: INVOCATION

D’UNE MÉTHODE

Object lancerMethode(Object o, Object[] args, String nomMethode) throws Exception {

Class[] paramTypes = null;

if(args != null) {

paramTypes = new Class[args.length];

for(int i=0;i<args.length;++i) { paramTypes[i] = args[i].getClass();

}

}

Method m = o.getClass() .getMethod(nomMethode,paramTypes);

return m.invoke(o,args);

}

Page 15: Introspection reflection

15EXERCICE: INSPECTEUR

DE CLASSE SIMPLE

Ecrire un inspecteur de classe simple capable de:

Lister toutes les signatures des méthodes de la classe d’un objet,

Lister tous les champs de la classes d’un objet: Déclaration du champ,

Valeur du champ,

Page 16: Introspection reflection

16AU DELÀ DES RÈGLES DE L'ENCAPSULATION

Ce que permet de faire l'API Reflection dépasse largement le cadre de l'encapsulation,

Jusqu'à présent nous avons consulté et agi sur des champs et méthodes publiques,

Cette API permet d'inspecter tous les éléments d'une classe, quelle que soit sa visibilité

Page 17: Introspection reflection

17

AU DELÀ DES RÈGLES DE L'ENCAPSULATION: TRANSGRESSIONS

Transgression 1 : visibilité d’un membre invisible

getDeclaredFields et getDeclaredMethods pour les membres publics, private et protected

Transgression 2: manipulation d’un membre invisible

setAccessible(boolean b) permet de faire sauter le verrou de sécurité

Page 18: Introspection reflection

18AU DELÀ DES RÈGLES DE

L'ENCAPSULATION:EXEMPLE

Soit une classe Secret avec un champ privé priv (String).

void modifierChamp(Secret s, String val) {Field f =

s.getClass().getDeclaredField("priv");f.setAccessible(true); f.set(s,val);

}

Page 19: Introspection reflection

19

AU DELÀ DES RÈGLES DE L'ENCAPSULATION:

PROTECTIONS

Il existe néanmoins des possibilités pour combler ce manque de protection.

La méthode setAccessible est définie dans la classe AccessibleObject (dont dérivent les classes Field, Method et Constructor).

Définir qui possède le droit d'appeler la méthode setAccessible en définissant un SecurityManager.

Dépasse le cadre de la présentation,

Consulter le paquetage java.security,