1. Présentation <BR /> L'agent est un modèle de conception, dont le but est de fournir un autre objet avec un proxy pour contrôler l'accès à un certain objet. La classe Proxy est responsable de la prétraitement des messages pour la classe du délégué, du filtrage des messages et du transfert des messages, et de la réalisation de traitement ultérieur après l'exécution du message par la classe du délégué. Pour maintenir la cohérence dans le comportement, les classes de proxy et les classes de délégué implémentent généralement la même interface.
Selon la période de création d'agent, les classes d'agent peuvent être divisées en deux types:
Proxy statique: le programmeur crée une classe de proxy ou un outil spécifique pour générer automatiquement le code source, puis le compiler. C'est-à-dire que le fichier .class de la classe proxy existe déjà avant l'exécution du programme.
Proxy dynamique: utilisez le mécanisme de réflexion pour créer et générer dynamiquement lorsque le programme est en cours d'exécution.
Présentez brièvement le proxy statique avant de mettre en œuvre le mécanisme de proxy dynamique.
2. Proxy statique <br /> Comme mentionné ci-dessus, les classes de proxy et les classes déléguées doivent généralement implémenter la même interface. Ce qui suit est de définir cette interface d'abord:
Service d'interface publique {public void add ();}La classe du délégué est une implémentation d'une interface, définie comme suit:
classe publique ServiceIMPl implémente le service {public void add () {System.out.println ("Ajouter un utilisateur!"); }}Si nous voulons ajouter des journaux à la classe du délégué, la classe proxy peut être définie comme suit:
Classe publique ServiceProxy implémente Service {Service privé; public ServiceProxy (Service Service) {super (); this.service = service; } public void add () {System.out.println ("Service Start"); service.add (); System.out.println ("Service End"); }}Écrire des classes de test:
classe publique TestMain {public static void main (String [] args) {Service ServiceImpl = new ServiceImpl (); Service Proxy = new ServiceProxy (ServiceImpl); proxy.add (); }}Exécutez le programme de test, les résultats sont les suivants:
À partir du code ci-dessus, nous pouvons voir que la classe de proxy statique ne peut servir qu'une interface spécifique. Si vous souhaitez desservir plusieurs types d'objets, vous devez proxyer chaque objet. Nous nous demanderons si toutes les fonctions proxy peuvent être remplies via une classe de proxy, nous avons donc introduit le concept de proxy dynamique.
3. Dynamic Proxy Java's Dynamic Proxy implique principalement deux classes, Proxy et InvocationHandler.
Proxy: fournit un ensemble de méthodes statiques pour générer dynamiquement des classes de proxy et leurs objets pour un ensemble d'interfaces.
// Méthode 1: Cette méthode est utilisée pour obtenir le processeur d'appel associé à l'objet proxy spécifié. static invocationhandler getInvocationHandler (objet proxy) // Méthode 2: Cette méthode est utilisée pour obtenir l'objet de classe de la classe de proxy dynamique associée au chargeur de classe spécifié et un ensemble d'interfaces. classe statique getProxyclass (classloader chargeur, class [] interfaces) // méthode 3: Cette méthode est utilisée pour déterminer si l'objet de classe spécifié est un proxy dynamique class static booléen isproxyclass (classe CL) // méthode 4: cette méthode est utilisée pour générer des instances de classe proxy dynamique pour le chargeur de classe spécifié, un ensemble d'interfaces et une définition d'interfaces. Objet statique NewProxyInstance (Classloader Loader, Class [] Interfaces, InvocationHandler H)
InvocationHandler: Il s'agit d'une interface processeur d'appel, personnalise une méthode d'invoquer, qui est utilisée pour gérer de manière centralisée les appels de méthode sur des objets de classe proxy dynamique, généralement dans lesquels l'accès proxy aux classes de délégué est implémenté
// Cette méthode est responsable de la gestion centrale de tous les appels de méthode sur la classe de proxy dynamique. Le premier paramètre est à la fois une instance de la classe proxy, et le deuxième paramètre est l'objet de méthode étant appelé // La troisième méthode est le paramètre d'appel. Le processeur d'appel prétraitement ou envoie à l'instance de classe de délégué pour transmettre un objet d'exécution invoquer (proxy d'objet, méthode de la méthode, objet [] args)
Pour implémenter un proxy dynamique pour Java, il existe quatre étapes spécifiques:
1. Créez votre propre processeur d'appel en implémentant l'interface invocationHandler
2. Créez une classe proxy dynamique en spécifiant l'objet Classloader et un ensemble d'interfaces pour la classe proxy
3. Obtenez le constructeur de la classe de proxy dynamique via le mécanisme de réflexion, et son seul type de paramètre est le type d'interface de classe de processeur d'appel
4. Créez une instance de classe de proxy dynamique via le constructeur. Pendant la construction, l'objet de processeur est appelé paramètre et est passé.
Ce qui suit est un exemple de mise en œuvre de votre propre proxy dynamique basé sur les quatre étapes ci-dessus:
La classe d'implémentation de l'interface et de l'interface (c'est-à-dire la classe Delegate) est la même que le code du proxy statique ci-dessus. Ici, nous implémenterons l'interface InvocationHandler pour créer notre propre processeur d'appels.
classe publique ServiceHandle implémente invocationHandler {private objet s; public ServiceHandle (Object S) {this.s = s; } public Object Invoke (Proxy d'objet, méthode de la méthode, objet [] args) lève throwable {System.out.println ("Service start"); // Invoque signifie appeler la méthode sous-jacente représentée par cet objet de méthode sur un objet spécifié avec des paramètres spécifiés objet résultat = méthode.invoke (s, args); System.out.println ("Service End"); Résultat de retour; }}Écrire des classes de test:
classe publique TestMain {public static void main (String [] args) {Service Service = new ServiceImpl (); InvocationHandler Handler = new ServiceHandle (service); Service S = (Service) proxy.newproxyinstance (service.getClass (). GetClassLoader (), service.getClass (). GetInterFaces (), Handler); S.Add (); }}Exécutez le programme de test et le résultat est le même que le proxy statique. Nous pouvons voir que le code ci-dessus n'a pas les étapes 2 et 3 que nous avons mentionnés auparavant, car la méthode statique de Prox NewProxyInstance a résumé ces deux étapes pour nous. L'implémentation interne spécifique est la suivante:
// Créez dynamiquement un objet de classe de la classe Proxy pour un ensemble d'interfaces, y compris l'interface d'interface via Proxy class Clazz = proxy.getProxyClass (Classloader, New Class [] {interface.class, ...}); // Objectif du constructeur à partir de l'objet de classe généré par réflexion Constructor = Clazz. une instance de classe de proxy dynamique via l'interface d'objet constructeur proxy = (interface) constructor.newinstance (nouvel objet [] {handler});La mise en œuvre interne de la fonction NewProxyInstance est:
Objet statique public NewProxyInstance (Classloader Loder, classe <?> [] Interfaces, invocationHandler h) lève illégalArgumentException {// vérifier h n'est pas vide, sinon jetez des objets exceptionnels.requirenonnull (h); // Obtenez l'objet de type de classe proxy lié à la formulation du chargeur de classe et à un ensemble d'interfaces final class <?> [] Intfs = interfaces.clone (); // Vérifiez si l'objet de classe d'interface est visible par le chargeur de classe et est exactement le même que l'objet de classe d'interface reconnue par le chargeur de classe Final SecurityManager sm = System.getSecurityManager (); if (sm! = null) {checkProxyAccess (Reflection.getCallerClass (), Loader, Intfs); } // Obtenez l'objet de type de classe proxy lié à la formulation du chargeur de classe et à un ensemble de classe d'interfaces <?> CL = getProxyClass0 (chargeur, intfs); essayez {if (sm! = null) {checkNewProxyPermission (réflexion.getCallerClass (), cl); } // Obtenez l'objet constructeur via la réflexion et générez une instance de classe proxy constructeur final <?> Cons = cl.getConstructor (ConstructorArams); Final InvocationHandler ih = h; if (! Modifier.ispublic (cl.getModifiers ())) {AccessController.Dopriviled (new privilEgEdAction <void> () {public void run () {cons.setAccessible (true); return null;}}); } return Cons.NewInstance (nouvel objet [] {h}); } Catch (illégalaccessException | InstantiationException e) {Throw New Internerror (e.ToString (), e); } catch (invocationTargetException e) {Throwable t = e.getCause (); if (t instanceof runtimeException) {throw (runtimeException) t; } else {lance un nouveau Internerror (t.ToString (), t); }} catch (NosuchMethodexception e) {Throw new interneerror (e.toString (), e); }} 4. Simuler et implémenter une classe proxy
Selon l'introduction du principe ci-dessus, nous pouvons simuler et mettre en œuvre la classe de procuration par nous-mêmes:
public class proxy {public static objet newProxyInstance (class inface, invocationhandle h) lève l'exception {string rt = "/ r / n"; String méthodestr = ""; Méthode [] méthodes = inface.getMethods (); pour (méthode m: méthodes) {methodstr + = "@ override" + rt + "public void" + m.getname () + "()" + rt + "{" + rt + "try {" + rt + "méthode md =" + inface.getname () + ". class.getMethod (/" "+ m.getname () +" / ");" + rt + "h.invoke (this, md);" + rt + "} catch (exception e) {e.printstackTrace ();}" + rt + "}"; } Chaîne src = "Test de package;" + rt + "Importer java.lang.reflect.method;" + rt + "classe publique ServiceIMPL2 implémente" + inface.getName () + rt + "{" + rt + "public ServiceImpl2 (invocationhandle h)" + rt + "{" + rt + "this.h = h;" + rt + "}" {"+ rt +" this.h = h; test.invocationhandle h; "+ rt + methodstr +"} "; String filename = "d: /src/test/serviceImpl2.java"; // compiler compile (src, nom de fichier); // Chargez dans la mémoire et créez un objet d'instance m = LoadMemory (H); retour m; } private static void compile (String src, string filename) lève ioException {file f = new File (nom de fichier); Filewriter filewriter = new FileWriter (f); filewriter.write (src); filewriter.flush (); filewriter.close (); // Obtenez le compilateur Java fourni par cette plate-forme, Javacompiler Compiler = toolsProvider.getSystemJavacompiler (); // Obtenez une nouvelle instance implémentée par un gestionnaire de fichiers standard StandardJavaFileManager FileManager = compiler.getStandardFileManager (null, null, null); // obtient l'objet de fichier représentant le fichier donné iTable Unités = fileManager.getJavaFileObjects (nom de fichier); // Créer une compilation futureTask t = compiler.getTask (null, filemanager, null, null, null, unités); // Exécuter cette tâche de compilation t.call (); FileManager.Close (); } Private Static Object LoadMemory (invocationHandle h) lève MalformEdUrException, classNotFoundException, NosuchMethodexception, InstantiationException, IllégalAccessException, invocationTargexception {url [] urls = new Url [] {new url ("fichier: /" + "d: / src /")}; // Classe de chargement et ressource URLClassloader UL = new UrlClassloader (URL); Classe C = ul.loadClass ("test.serviceIMPL2"); // Renvoie le constructeur public spécifié de la classe représentée par l'objet de classe. Constructeur Ctr = C.GetConstructor (invocationHandle.class); // Utilisez la méthode du constructeur représenté par cet objet constructeur CTR pour créer une nouvelle instance de la classe de déclaration de la méthode du constructeur, et initialisez l'instance avec l'objet de paramètre d'initialisation spécifié m = ctr.newinstance (h); retour m; }}5. Résumé 1. Le soi-disant proxy dynamique est une telle classe. C'est une classe générée à l'exécution. Lorsque vous la générez, vous devez lui fournir un ensemble d'interfaces, puis modifier la classe pour affirmer qu'il implémente ces interfaces. Cependant, il ne fera pas de travail substantiel pour vous, mais reprendra le travail réel en fonction du gestionnaire de paramètres (c'est-à-dire la classe d'implémentation de l'interface invocationhandler) fournie lorsque vous générez l'instance.
2. La conception de Proxy le fait de prendre en charge le proxy d'interface. Le mécanisme d'héritage de Java a destiné que la classe de proxy dynamique ne peut pas implémenter le proxy dynamique pour la classe, car l'héritage multiple n'est essentiellement pas possible en Java.
Ce qui précède concerne cet article, j'espère qu'il sera utile à l'apprentissage de tout le monde.