Proxy et plus Cnam Paris jean-michel Douin, douin au cnam point fr Nouvelle version : 4 Septembre 2005 Notes de cours java : le langage : Introduction, approche impérative
Sommaire La famille Proxy Les Parents [Gof95] Les descendants VirtualProxy RemoteProxy DynamicProxy
Bibliographie utilisée Design Patterns, catalogue de modèles de conception réutilisables de Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides [Gof95] International thomson publishing France Mark Grand http://www.ida.liu.se/~uweas/Lectures/DesignPatterns01/panas-pattern-hatching.ppt http://www.mindspring.com/~mgrand/pattern_synopses.htm
Objectifs Proxy-Procuration Alias Motivation Fournit à un tiers objet un mandataire, pour contrôler l ’accès à cet objet Alias Subrogé (surrogate) Motivation contrôler différer optimiser sécuriser ...
realSubject->request(); Diagramme UML Subject request() … realSubject->request(); RealSubject request() … Proxy request() … realSubject L ’original
Une instance possible du pattern proxy http://www.theserverside.com/tt/articles/content/JIApresentations/Kabutz.pdf
le Service/Sujet public interface Service{ offrir(Bouquet b) … public interface Service{ /** Offrir un bouquet de fleurs * @param bouquet le bouquet * @return réussite ou échec ... */ public boolean offrir(Bouquet b); }
Une implémentation du Service ServiceImpl offrir(Bouquet b) … public class ServiceImpl implements Service{ public boolean offrir(Bouquet b){ System.out.println(" recevez ce bouquet : " + b); return true; }
Offrir en « direct » Client offrir(unBouquet) Console... Service service = new ServiceImpl(); assert service.offrir(unBouquet) == true;
Le mandataire public class ServiceProxy implements Service{ service.offrir(b) public class ServiceProxy implements Service{ private ServiceImpl service; public ServiceProxy(){ this.service = new ServiceImpl(); } public boolean offrir(Bouquet bouquet){ boolean résultat; System.out.print(" par procuration : "); résultat = service.offrir(bouquet); return résultat; } } ServiceProxy offrir(Bouquet b) …
Offrir par l ’intermédiaire de ServiceProxy Console ... Client offrir(unBouquet) offrir(unBouquet) Service service = new ServiceProxy(); service.offrir(unBouquet);
VirtualProxy Création d ’objets « lourds » à la demande Coût de la création d ’une instance Création d ’un objet seulement si nécessaire
Virtual (lazy) Proxy public class VirtualProxy implements Service{ private Service service; public boolean offrir(Bouquet bouquet){ boolean résultat; System.out.print(" par procuration, virtualProxy (lazy) : "); Service service = getServiceImpl(); résultat = service.offrir(bouquet); return résultat; }
VirtualProxy & Introspection private Service getServiceImpl(){ if(service==null){ try{ Class classe = Class.forName("ServiceImpl"); service = (Service) classe.newInstance(); }catch(Exception e){ e.printStackTrace(); } return service;
La « famille » avec BlueJ
Sécurité … VirtualProxy bis URLClassLoader hérite de SecureClassLoader Il peut servir à « vérifier » un code avant son exécution souvent associé à une stratégie de sécurité private Service getServiceImpl(){ if(service==null){ try{ ClassLoader classLoader = new URLClassLoader( new URL[]{new URL("http://jfod.cnam.fr/nsy102/proxy_pattern.jar")}); Class classe = Class.forName("ServiceImpl",true, classLoader); service = (Service) classe.newInstance(); }catch(Exception e){ e.printStackTrace(); } return service;
Résumé, bilan intermédiaire Procuration à un tiers Proxy contrôle complet de l ’accès au sujet réel VirtualProxy des contraintes de coûts en temps d ’exécution liée à une stratégie de sécurité ? Connaissance à l ’exécution du sujet réel ? ? Procuration pour un appel distant en complète « transparence » ?
un cousin plutôt dynamique et standard extrait de l ’API du J2SE Dynamic Proxy http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/InvocationHandler.html http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Proxy.html L ’interface à implémenter interface java.lang.reflect.InvocationHandler; ne contient qu ’une seule méthode Object invoke( Object proxy, Method m, Object[] args); proxy : le contexte de l ’appelé, XXXClassLoader m : la méthode sélectionnée args : les arguments de cette méthode
DynamicEtProxy public class DynamicEtProxy implements InvocationHandler{ private ServiceImpl service; public DynamicEtProxy(){ this.service = new ServiceImpl(); } public Object invoke(Object proxy, Method method, Object[] args) throws Exception{ System.out.print(" par procuration dynamique : "); return method.invoke(service, args);
Dynamic Proxy Client Console ... Proxy InvocationHandler offrir(unBouquet) invoke(service,args) invoke() ClassLoader cl = Service.class.getClassLoader(); Service service = (Service) Proxy.newProxyInstance(cl, new Class[]{Service.class}, new DynamicEtProxy()); service.offrir(unBouquet);
Doit-on connaître le nom de la classe ? VirtualProxyBis, le retour ClassLoader cl = new URLClassLoader( new URL[]{new URL("http://jfod.cnam.fr/csiml/proxy_pattern.jar")}); Class classe = Class.forName("DynamicEtProxy",true, cl); InvocationHandler handler = (InvocationHandler)classe.newInstance(); Service service = (Service) Proxy.newProxyInstance(cl, new Class[]{Service.class}, handler); service.offrir(unBouquet); } encore plus dynamique ? Plus générique ?
DynamicProxy et le pattern décorateur
Le petit dernier Une procuration à distance
un petit dernier http://www.mindspring.com/~mgrand/pattern_synopses.htm
Java RMI utilise les DynamicProxy appel distant transparents génération des « stubs »
Pourquoi
Exemple