JavaBean 3

Réflexion

Source de Inspecteur.java du package inspect
package inspect;
import java.util.*;
import java.lang.reflect.*;
public class Inspecteur {
  private Class laClass;
  public Inspecteur(Class c) {
    if (c == null)
      throw new IllegalArgumentException("classe null");
    else
      laClass = c;
  }
  public Inspecteur(Object obj) {
    if (obj == null)
      throw new IllegalArgumentException("objet null");
    else
      laClass = obj.getClass();
  }
  public String classe() {
    return laClass.getName(); 
  }
  public String heritage() {
    return heritage(laClass);
  }
  private String heritage(Class uneClasse) {
    if  (uneClasse == null) 
      throw new IllegalArgumentException("classe null");
    else {
      Class classeMere = uneClasse.getSuperclass();
      if (classeMere == null) 
        return Object.class.getName() + "\n";
      else 
        return uneClasse.getName() + "\n" 
                + heritage(classeMere);   
    }
  }
  public String[] listeMethodes() {
    Method[] methodes = laClass.getMethods();
    String[] tabMethods = new String[methodes.length];
    for (int i = 0; i<methodes.length; i++)
      tabMethods[i] = methodes[i].getName();
    return tabMethods;
  }
  public String inspecteMethode(int pos)  {
    Method[] methodes = laClass.getMethods();
    if ((pos < 0) || (pos >= methodes.length))
      throw new IllegalArgumentException(" mauvaise position : " + pos);
    else {
      Method laMethode = methodes[pos];
      StringBuffer s = new StringBuffer("methode : ");
      s.append(laMethode.getName()+"\n");
      s.append("  modifieurs : " 
               + Modifier.toString(laMethode.getModifiers()) + "\n");
      s.append("  retourne : " 
               + laMethode.getReturnType().getName() + "\n");
      Class [] typeParams = laMethode.getParameterTypes();
      for (int i = 0 ; i < typeParams.length ; i++)
	s.append("  parametre : " + typeParams[i].getName()+"\n");     
      return s.toString();
    }
  }
  public String[] listeAttributs() {
    Field []attributs = laClass.getDeclaredFields();
    String[] tabAttributs = new String[attributs.length];
    for (int i = 0; i<attributs.length; i++) 
      tabAttributs[i] = attributs[i].getName();
    return tabAttributs;
  }
  public String inspecteAttribut (int pos) {
    Field [] attributs = laClass.getDeclaredFields();
    if ((pos < 0) || (pos >= attributs.length))
      throw new IllegalArgumentException(" mauvaise position : " + pos);
    else {
      Field lAttribut = attributs[pos];
      StringBuffer s = new StringBuffer("Attribut : ");
      s.append(lAttribut.getName()+"\n");
      s.append("  type : " 
               + lAttribut.getType().getName() + "\n");
      s.append("  modifieurs : " 
               + Modifier.toString(lAttribut.getModifiers()) + "\n");
      return s.toString();
    }
  }
}

 Source de Inspection.java du package inspect
package inspect;

public class Inspection extends Frame
                 implements ItemListener {
    private Inspecteur inspecteur = null;
  private java.awt.List liste;
  private TextArea textResult;
  private CheckboxGroup choix; 
  public static void main(String args[]) {
    if (args.length == 1) {
      try {
        Class c = Class.forName(args[0]);
        Inspecteur inspecteur = new Inspecteur(c); 
        new Inspection(inspecteur);
      } catch (ClassNotFoundException e) {
        System.out.println(e);
      }
    } else
      System.out.println("manque l'argument nom de classe");
  }
  public Inspection(Inspecteur insp) {
   ...

EXECUTION
$ java inspect.Inspection prophet5.Prophete


  • les lignes de la classe :
    • On affiche les attributs, les méthodes et les classes héritées de prophet5.Prophète
    • ces infos sont stokées dans un objet particulier qui représente la classe prophet5.Prophète

 

Introspection d'un bean

Les IDEs (interface ...) permettent de manipuler aisément les objets et les classes : grace à l'introspection du langage Java, des "Explorers" visualise immédiatement les attributs, les méthodes ainsi que leur type, leur modifier d'accès et pour les méthodes leur signature. Qu'en est'il des caractéristiques des beans ?

Source de InspecteurProphet.java
package prophet3;
import java.beans.*;
class InspecteurProphet{
  public static void main(String args[]) {
    Prophete prophete = new Prophete("Brian");
    System.out.println ("Inspection de "
                        + prophete.getClass().getName() +"\n");
    try {
      BeanInfo bi =  Introspector.getBeanInfo (prophete.getClass());
      System.out.println ("getBeanInfo ShortDescription : " 
                     +  bi.getBeanDescriptor().getShortDescription() + "\n");      
      EventSetDescriptor[] esd = bi.getEventSetDescriptors();
      System.out.println ("EventSetDescriptor : \n");
      for (int i=0;i<esd.length;i++)
	  System.out.print ("  " + esd[i].getName() + " ");
      System.out.println ("\n");
      
      PropertyDescriptor pd[] = bi.getPropertyDescriptors();
      System.out.println ("PropertyDescriptor : \n");
      for (int i=0;i<pd.length;i++)
	  System.out.print ("  " + pd[i].getName() + " ");
      System.out.println ("\n");
      
      MethodDescriptor md[] = bi.getMethodDescriptors();
      System.out.println ("MethodDescriptor : \n");
      for (int i=0;i<md.length;i++)
	  System.out.print ("  " + md[i].getName() + " ");
      System.out.println ("\n");   
    } catch (IntrospectionException e) {
      System.out.println ("impossible de trouver le BeanInfo de "
      + prophete.getClass().getName() + "\n"
      + e.getMessage());
    }   
  }
}

les sources du package prophet3
EXECUTION
$ java InspecteurProphet      
Inspection de prophet3.Prophete
getBeanInfo ShortDescription : Prophete
EventSetDescriptor : 
  vetoableChange   propertyChange 
PropertyDescriptor : 
  class   nom   prophetie 
MethodDescriptor : 
  hashCode   removeVetoableChangeListener
   removePropertyChangeListener   addPropertyChangeListener
   getProphetie   equals   wait   wait   notify   getClass
   toString   notifyAll   wait   setProphetie 
  addVetoableChangeListener   getNom
  • les lignes de la classe :
    • Introspection du bean prophet3.Prophete
      • l'Introspector appelle la méthode getBeanInfo() pour obtenir les caractéristiques spécifiques du bean
      • Visiblement, elle sont les mêmes que celles obtenues par la simple réflexion !

beanInfo

Source de PropheteBeanInfo.java du package prophet4
package prophet4;
import java.beans.*;
import java.lang.reflect.*;
public class PropheteBeanInfo extends SimpleBeanInfo {  
  public PropheteBeanInfo() {
    super();
  }  
  public BeanDescriptor getBeanDescriptor() {
    BeanDescriptor bd = new BeanDescriptor(prophet4.Prophete.class);
    bd.setDisplayName("Prophete");
    bd.setShortDescription("un illumine de plus !");
    return bd;
  }    
  public EventSetDescriptor[] getEventSetDescriptors() {
    try {
      EventSetDescriptor[] eds = {
	new EventSetDescriptor(Prophete.class, "PropertyChange",
                 PropertyChangeListener.class, "propertyChange")};
      return eds;	                      
    }
    catch (IntrospectionException e) {
      e.printStackTrace(); 
    }
    return null;
  }  
  public MethodDescriptor[] getMethodDescriptors() {
    Class c = Prophete.class;
    try {
      Method getter1 = c.getMethod("getNom", null);
      MethodDescriptor md1 = new MethodDescriptor(getter1);
      md1.setShortDescription("donne le nom du prophete");
      Method getter2 = c.getMethod("getProphetie", null);
      MethodDescriptor md2 = new MethodDescriptor(getter2);
      md2.setShortDescription("donne la prophetie");
      Class[] params = { String.class };
      Method setter3 = c.getMethod("setProphetie", params);
      MethodDescriptor md3 = new MethodDescriptor(setter3);
      md3.setShortDescription("change de prophetie");
      MethodDescriptor[] mds = { md1, md2, md3};
      return mds;
    } catch (NoSuchMethodException e) {
      e.printStackTrace(); 
    }
    return null;
  }  
  public PropertyDescriptor[] getPropertyDescriptors() {
    PropertyDescriptor pd1 = null;
    PropertyDescriptor pd2 = null;
    try {
      pd1 = new PropertyDescriptor("nom", Prophete.class, "getNom", null);
      pd1.setDisplayName("nomDuProphete");
      pd2 = new PropertyDescriptor("prophetie", Prophete.class,
                                   "getProphetie","setProphetie");
      pd2.setDisplayName("prophetieDuProphete");
      pd2.setBound(true);
      pd2.setConstrained(true);
    } catch (IntrospectionException e) {
      e.printStackTrace(); 
    }
    PropertyDescriptor[] pds = { pd1, pd2 };
    return pds; 
  } 
}

les sources du package prophet4
qui contient le bean Prophete avec une propriété liée et une propriété contrainte.
L'InspecteurProphet est inchangé.
EXECUTION
$java  prophet4.InspecteurProphet
Inspection de prophet4.Prophete
getBeanInfo ShortDescription : un illumine de plus !
EventSetDescriptor : 
  PropertyChange 
PropertyDescriptor : 
  nom   prophetie 
getMethodDescriptor : 
  getProphetie   setProphetie   getNom
  • les lignes de la classe :
    • C'est le même programme InspecteurProphet que dans prophet3
    • les informations obtenues sont différentes : elles concernent bien uniquement les propriétés, accesseurs du bean, exception faite qu'il manque un événement puisqu'il n'a pas été renseigné !
    • L'introspection a bien trouvé le ProphetBeanInfo qui a été renseigné.

Résumé des Patterns d'un JavaBean

exercices