Salut,
La classe proxy permet d'implémenter dynamiquement des interfaces.
En gros cela te permet d'obtenir un objet implémentant une ou plusieurs interfaces, dont tous les appels seront redirigé vers la méthode invoke() de l'InvocationHandler.
Cela te permet de faire des traitements génériques en récupérant les infos via la reflection, touten manipulant un objet de manière standard...
Par exemple grosso-modo pour créer automatiquement des implémentations qui se contente de logger les appels de méthodes, il faudrait utiliser ceci :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class LoggerInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if (method.getDeclaringClass()==Object.class) {
// S'il s'agit d'une méthode de Object,
// on l'invoke sur l'instance du handler :
return method.invoke(this, args);
} else {
// Sinon on effectue notre traitement dynamique,
// par exemple logger l'appel de la méthode :
System.out.printf("%s => %s()%n", new Date(), method.getName());
if (args!=null) {
for (Object o : args) {
System.out.printf("\t%s%n", o);
}
}
// Nota : en réalité ici il faudrait gérer les types primitifs
// ( par exemple si "int" retourner Integer.valueOf(0) )
return null;
}
}
} |
Qui s'utilise ensuite de la manière suivante :
1 2 3 4 5 6 7
| @SuppressWarnings("unchecked")
public static <T> T create(Class<T> interfaceType) {
return (T) Proxy.newProxyInstance(
interfaceType.getClassLoader(),
new Class<?>[]{interfaceType},
new LoggerInvocationHandler());
} |
Exemple :
1 2 3 4
| // On crée un objet de type Runnable :
Runnable runnable = create(Runnable.class);
// Que l'on utilise de façons tout à fait normale :
runnable.run(); |
Ce qui donnerait :
Sat Dec 20 09:28:37 CET 2008 => run()
Ou un autre exemple un peu plus concret : générer des listeners dynamiques :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| // On crée un composant graphique :
JButton button = new JButton("button");
// On lui ajoute plein de listener :
button.addActionListener(create(ActionListener.class));
button.addAncestorListener(create(AncestorListener.class));
button.addChangeListener(create(ChangeListener.class));
button.addComponentListener(create(ComponentListener.class));
button.addContainerListener(create(ContainerListener.class));
button.addFocusListener(create(FocusListener.class));
button.addHierarchyBoundsListener(create(HierarchyBoundsListener.class));
button.addHierarchyListener(create(HierarchyListener.class));
button.addInputMethodListener(create(InputMethodListener.class));
button.addItemListener(create(ItemListener.class));
button.addKeyListener(create(KeyListener.class));
button.addMouseListener(create(MouseListener.class));
button.addMouseMotionListener(create(MouseMotionListener.class));
button.addMouseWheelListener(create(MouseWheelListener.class));
button.addPropertyChangeListener(create(PropertyChangeListener.class));
// On affiche le composant, pour tester ses listeners
JOptionPane.showMessageDialog(null, button); |
a++
Partager