Bases: Il nécessite des idées de conception orientées objet, des idées polymorphes et des idées de réflexion;
L'émergence du mécanisme de proxy dynamique Java permet aux développeurs Java d'obtenir dynamiquement des classes de proxy sans avoir à écrire manuellement des classes de proxy. La classe Proxy est responsable de la suppression de tous les appels de méthode à l'objet délégué pour refléter l'exécution. Pendant le processus d'exécution de répartition, les développeurs peuvent également ajuster l'objet délégué et ses fonctions au besoin. Il s'agit d'un cadre proxy très flexible et flexible. En lisant cet article, les lecteurs auront une compréhension plus approfondie du mécanisme de proxy dynamique Java. Cet article analyse d'abord le code basé sur le mécanisme de fonctionnement et les caractéristiques du proxy dynamique Java et déduit la mise en œuvre interne des classes de génération dynamique.
Concepts de base et classification du modèle d'agent
Mode proxy: fournit un proxy pour d'autres objets pour contrôler l'accès à cet objet. L'objet proxy agit comme un intermédiaire et peut supprimer des services ou ajouter des services supplémentaires, ou citer d'autres: "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 déléguée."
Scénarios d'application du mode agent en développement
Proxy à distance: fournit des objets représentatifs LAN pour les objets de différentes régions géographiques.
Agent virtuel: retardez des objets qui consomment beaucoup de ressources selon les besoins et les créez lorsqu'ils sont vraiment nécessaires. Par exemple, le texte s'affiche d'abord, puis l'image s'affiche sur la page Web.
Agent de protection: contrôle les droits d'accès des différents utilisateurs. Par exemple: ce n'est qu'après que l'enregistrement du client soit réussi peut ajouter, supprimer, modifier et vérifier les opérations.
Agent de référence intelligent: fournit des services supplémentaires à l'agent cible.
Comment implémenter le mode proxy
Lequel est préférable d'implémenter un proxy dynamique en utilisant l'héritage et l'agrégation!
Interface publique Moveable {public void move ();} public class car implémente Moveable {@Override public void move () {try {thread.sleep (new random (). NextInt (1000)); System.out.println ("... Driving ...");} Catch (InterruptedException e) {// too a-to-généré un bloc de capture E. PrintStackTrace (); étend la voiture {@Override public void move () {// séparez le code, augmentez la logique métier long starttime = System.currenttimemillis (); System.out.println ("la voiture commence à conduire ..."); super.move (); longue fin = System.currenttimemillis (); System.out.println ("La voiture se termine par la voiture ... "+ (fin de starttime) +" MS ");}}Méthode d'héritage pour implémenter le proxy
Moveablecar2=newCar2();
car2.move();
La méthode d'agrégation implémente le proxy
Carcar=newCar();
Moveablem=newCar3(car);
m.move();
Résumer
La méthode d'héritage n'est pas assez flexible. Lorsque les fonctions sont superposées, vous ne pouvez étendre que la classe proxy ne fait pas de rôle;
En utilisant l'agrégation, les agents peuvent être transmis les uns aux autres et un proxy peut être combiné de manière flexible;
classe publique CarlogProxy étend la voiture {@Override public void move () {// séparez le code et augmentez la logique commerciale long starttime = System.currenttimemillis (); System.out.println ("Login start ..."); super.move (); Long EndTime = System.currenttimemillis (); System.out.TrprintLn ("Loggin End ...; Cartimeproxy implémente Moveable {public cartiméproxy (voiture voiture) {super (); this.car = car;} Carcar privé; @Override public void move () {// sépare le code et ajouter la logique commerciale long starttime = System.currenttimemillis (); System.out.println ("La voiture commence à conduire ..."); Car.Move (); Fintime = System.CurrentTimeMillis (); System.out.println ("La voiture se termine pour conduire ... le temps:" + (Startime de fin) + "MS");}} @ Test: Car Car = New Car (); cartimeproxy ctp = new Cartimeproxy (Car); CarlogProxy Clp = new Carlogproxy (ctp); clp.move (); // vous pouvez également se transmettre des instances proxy via les interfaces carlogproxy clp1 = new carlogproxy (car); cartimeproxy ctp1 = nouveau cartimeproxy (CLP1); ctp1.move ();Proxy dynamique JDK et proxy dynamique CGLIB
Proxy dynamique JDK
Mise en œuvre de l'agent
Que faire si différents objets souhaitent implémenter la classe de proxy avec la même fonction?
Pour le moment, vous pouvez essayer de l'intégrer dans la même classe de proxy ------- Proxy dynamique: implémentation de proxy pour différentes classes / méthodes différentes;
Le processus général est le suivant:
La classe de proxy dynamique Java est située dans le package java.lang.reflect, qui implique généralement principalement les deux classes suivantes:
(1.
OBJ: fait généralement référence à la classe proxy
Méthode: est la méthode proxy
Args est un tableau de paramètres pour cette méthode.
Cette méthode abstraite est implémentée dynamiquement dans la classe proxy.
(2) Proxy: cette classe est une classe de proxy dynamique
statixObjectnewProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandlerh)
Renvoie une instance de la classe Glycoside, et la classe de proxy renvoyée peut être utilisée comme classe proxy (vous pouvez utiliser la méthode déclarée dans l'interface par la classe proxy);
Exemple d'implémentation:
@ TimeHandler classe publique TimeHandler implémente InvocationHandler {public timeHandler (objet Target) {super (); this.target = cible;} objet privétTarget; / * * Paramètres: * Valeur de retour proxy proxy * méthode méthode d'objet proxy * Args Paramètre * * Valeur de retour: * Méthode d'objet starttime = System.CurrentTimemillis (); System.out.println ("La voiture commence à conduire ..."); méthode.invoke (cible); Long Budtime = System.Currenttimemillis (); System.out.println ("la voiture se termine à conduire ... le temps:" + (fin de temps de fin de temps) + "ms"); retour null;}}} @La interface de la classe proxy Interface publique Moveable {public void move ();} @ la classe proxy Classe publique CART implémente Moveable {@Override public void move () {try {thread.sleep (new Random (). NextInt (1000)); System.out.println ("... Driving ...");} Catch (InterruptedException e) {// Todo Generated Catch Block E.PrintStackTrace ();}}@test
Classe publique Test {/ ** * JDK Dynamic Proxy Test Classe * / public static void main (String [] args) {Car car = new Car (); InvocationHandler h = new TimeHandler (voiture); Classe <?> CLS = car.getClass (); / * * Classe de chargeur Chardeur * Interfaces Implémentation d'interface * H InvocationHandler * / Moveable M = (Moveable) proxy.newProxyInstance (cls.getClassloadher (), cls.getInterfaces (), h); M.Move (); }}&& Résultats des tests
Résumé
Le dynamicproxy est une telle classe:
C'est une classe générée à l'exécution. Cette classe doit implémenter un ensemble d'interfaces. Lorsque vous utilisez des classes de proxy dynamiques, l'interface invocationHandler doit être implémentée.
Étapes générales pour le proxy dynamique JDK
1. Créez une classe qui implémente l'interface InvocationHandler, qui doit implémenter invoke ()
2. Créez la classe et l'interface proxy
3. Appelez la méthode statique de Proxy pour créer une classe de proxy
newProxyInstance (classloaderloader, classe [] interfaces, invocationhandlerh)
4. Appelez les méthodes par proxy
Implémentation du proxy dynamique CGLIB
Mise en œuvre de l'agent
@Introducing cglib-node-2.2.jar package
@Cglibproxy interception classe implémente la méthode d'interface Intercept: réécriture de la méthode d'interception
classe publique CGLIBProxy implémente MethodInterceptor {private EnhanceRenHancer = new Enhancer (); public objet getProxy (class cl) {// définir la classe qui crée une sous-classe Enhancer.SetSuperclass (CL); Enhancer.SetCallback (this); Retour Amplace Méthode * Méthode args * Instance proxy de la classe proxy * * / @ Override Intercept de l'objet public (objet obj, méthode m, objet [] args, méthode proxy) lance Throws {System.out.println ("Login start ..."); // la classe proxy appelle la méthode de la classe parent. fin ... "); retour null;}}Train de classe @proxy
classe publique Train {public void move () {System.out.println ("Le train conduit ..."); }}Classe @Test
Classe publique Test {/ ** * CGLIBPROXY Dynamic Proxy Test Classe * / public static void main (String [] args) {cglibproxy proxy = new Cglibproxy (); Train t = (train) proxy.getProxy (train.class); t.move (); }}## Résultats des tests:
Résumé
Étapes générales pour implémenter un proxy dynamique à l'aide de cglibproxy
1. Créez une classe pour implémenter la méthode d'interface Interceptor et remplacer la méthode d'interception
2. Créez une classe proxy
3. Appelez la méthode personnalisée de la classe proxy pour obtenir une instance proxy
4. Appelez la méthode qui doit être exécutée par l'instance proxy
Résumé comparatif
Proxy dynamique JDK
1. Seules les classes proxy qui implémentent les interfaces
2. Les classes sans interface ne peuvent pas implémenter un proxy dynamique pour JDK
Proxy dynamique CGLIB
1. Implémentation de proxy pour les classes
2. Générez une sous-classe vers la classe cible d'exécution et utilisez la méthode interceptant la technologie pour intercepter tous les appels de méthodes de classe parent.
Simuler les étapes de la génération d'agents
Idées:
Fonction d'implémentation: renvoyez l'objet proxy via NewProxyInstance de Proxy
1. Déclarer un code source (agent de génération dynamique)
2. Compilez le code source (jdkcompilerapi) pour générer de nouvelles classes (classes proxy)
3. Chargez cette classe en mémoire et générez un nouvel objet (objet proxy)
4. Renvoyez l'objet proxy
Améliorer la mise en œuvre de proxy dynamique
Tout d'abord, nous obtenons le compilateur système, obtenons le gestionnaire de fichiers via le compilateur, puis obtenons le fichier. Le compilateur effectue ensuite la tâche de compilation. Après avoir terminé la compilation, nous chargeons le fichier de classe dans le chargeur de classe, obtenons l'instance via la méthode du constructeur, puis appelons NewInstance () pour recevoir une instance d'un objet.
(1) Obtenez le compilateur javacompilerCompiler = TOLLProvider.getSystemJavacompiler ();
(2) File Manager StandardJavaFileManagerFilemgr = compiler.getStandardFileManager (null, null, null);
(3) Obtenez le fichier iTableMunits = fileMgr.getJavaFileObjects (nom de fichier);
(4) Tâche de compilation CompilationTaskt = compiler.getTask (null, fileMgr, null, null, null, null, unités);
(5) Chargez à la mémoire
ClassloaderCl = classloadher.getSystemClassLoader ();
Classc = cl.loadClass ("com.imooc.proxy. $ Proxy0");
(6) Construisez une instance via le constructeur de l'objet proxy
Constructorctr = c.getConstructor (infce);
Ctr.NewInstance (newCar ());
--------
Comme mentionné ci-dessus, la logique commerciale interne est codée en dur. Comment implémenter le véritable proxy dynamique et la logique métier désignée dynamiquement?
1. Vous devez créer un processeur de transaction. Tout d'abord, vous créez une interface, c'est-à-dire InvocationHandler. Afin de simuler JDK, le nom de l'interface est le même que le nom du processeur de transaction JDK. Vous écrivez également une méthode appelée invoke (), qui est utilisée pour représenter une certaine méthode d'un objet pour le traitement commercial. Par conséquent, vous devez passer un certain objet et la méthode de l'objet comme paramètres de la méthode invoke (). Invoke (objectObj, MethodMethod), la méthode utilisée comme paramètre pour la réflexion Java, et ce package doit être introduit. De cette façon, l'interface InvocationHandler est terminée.
2. Créer des classes d'implémentation de traitement des transactions, telles que TimerProxy, pour implémenter l'interface invocationhandler, de sorte que la structure devient
- ―oie len - ―oie `` arele - `` are
Vous devez passer l'objet cible. Si vous n'avez pas de paramètres, vous ne pouvez pas écrire de paramètres. Créez une méthode de construction d'objet proxy et initialisez l'objet cible.
3. Dans la méthode newProxyInstance () de la classe de proxy, en plus d'utiliser l'interface de classe cible comme paramètre, vous devez également passer le processeur de transaction InvocationHandler, puis modifier la partie codée dure de l'objet d'instance créé et utiliser la méthode du processeur de transaction pour le remplacer. La difficulté réside dans l'épissage des cordes.
Résumer
Dans notre projet, le modèle d'agent a sa propre signification pratique. Par exemple, si nous voulons appeler une classe sous un certain package JAR, nous pouvons ajouter une logique commerciale spéciale avant d'appeler cette classe. Cette méthode est également appelée programmation orientée AOP. (Ajouter des fonctions supplémentaires sans modifier les fonctions d'origine.)
Ce qui précède est toute l'explication détaillée du code de proxy dynamique Java (modèle de conception) dans cet article, j'espère que cela sera utile à tout le monde. Les amis intéressés peuvent continuer à se référer à d'autres sujets connexes sur ce site. S'il y a des lacunes, veuillez laisser un message pour le signaler. Merci vos amis pour votre soutien pour ce site!