English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Retrofit est un cadre de requêtes réseau très décorrélé, lors de la recherche récente, j'ai découvert une technologie d'agent dynamique très puissante et pratique. Cet article servira de connaissance préalable à Retrofit pour que vous puissiez comprendre : quels sont les scénarios d'application de l'agent dynamique, qu'est-ce que l'agent dynamique, comment l'utiliser, et où se trouvent ses limites ?
Scénarios d'application du proxy dynamique
1. AOP—Programmation orientée aspect, dé耦 des programmes
En résumé, lorsque vous souhaitez effectuer des opérations communes avant et après l'exécution de certaines méthodes internes d'une classe, tout en exécutant des opérations personnalisées dans les méthodes--Utiliser le proxy dynamique. Il peut réduire la quantité de code et améliorer la maintenabilité lors de la grande quantité de travail.
2. Personnaliser certaines méthodes d'une bibliothèque tierce
J'ai utilisé une bibliothèque tierce, mais certaines de ses méthodes ne répondent pas à mes besoins, je veux les réécrire ou ajouter des opérations spéciales avant et après les méthodes--Utiliser le proxy dynamique. Mais il faut noter que ces méthodes ont des limites, je l'expliquerai plus tard.
Qu'est-ce que le proxy dynamique
Les graphiques ci-dessus sont trop abstraits, commençons par des exemples de la vie réelle.
Imaginons que vous êtes un grand propriétaire (mandant), vous avez de nombreuses propriétés à louer, et vous trouvez que trouver des locataires est ennuyeux, vous ne souhaitez pas vous en occuper vous-même, donc vous trouvez quelqu'un pour vous mandater (mandataire), pour gérer ces choses, et cette personne (mandataire, c'est-à-dire l'agent immobilier) vous facture des frais de mandat correspondants (opérations supplémentaires sur la location de propriété) en vous aidant à louer des propriétés. Pour le locataire, l'agent immobilier est le propriétaire, et il vous aide à faire certaines choses.
En résumé, voici un exemple de proxy, et pourquoi il est appelé "proxy dynamique", où se trouvent les deux mots "dynamique" ?
Nous pouvons ainsi imaginer que si vous avez un agent pour chaque propriété, chaque fois que vous souhaitez louer une nouvelle propriété, vous devez engager un autre agent, ce qui entraînera un grand nombre d'agents, avec des coûts élevés en termes de mandats immobiliers, ce qui peut être considéré comme une "proxy statique".
Mais imaginons que nous confions toutes les propriétés à un agent immobilier pour le mandat, en lui permettant de passer dynamiquement d'une propriété à l'autre, pour vous aider à gérer chaque locataire. C'est un processus de "proxy dynamique". Une des grandes caractéristiques du proxy dynamique est qu'aucune classe proxy n'est exécutée au niveau de la compilation, mais est générée au niveau de l'exécution.
Voyons un exemple de code pour cela
Opérations de location de propriété
/** *Définir une interface **/ public interface RentHouse { void rent();//Location de propriété void charge(String str);//Taxe de location de propriété }
Landlord
public class HouseOwner implements RentHouse { public void rent() { System.out.println("I want to rent my house"); } public void charge(String str) { System.out.println("You get : ") + str + "RMB HouseCharge."); } }
Agency
public class DynamicProxy implements InvocationHandler { // C'est l'objet réel que nous devons proxy, c'est-à-dire le propriétaire private Object subject; // Constructeur, assigner la valeur initiale à l'objet réel que nous devons proxy public DynamicProxy(Object subject) { this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Nous pouvons ajouter nos propres opérations avant l'proxy de l'objet réel, et la commission d'agence est perçue System.out.println("before "+method.getName()+" house"); System.out.println("Method:") + method.getName()); // Si la méthode est 'charge', la commission est perçue par l'agence100 yuan agency fee. if (method.getName().equals("charge")) { method.invoke(subject, args); System.out.println("I will get 100 RMB ProxyCharge."); } else { // Lorsque l'objet proxy appelle une méthode de l'objet réel, il saute automatiquement vers la méthode invoke de l'objet handler associé pour l'appel method.invoke(subject, args); } // Nous pouvons également ajouter nos propres opérations après l'proxy de l'objet réel System.out.println("after "+method.getName()+" house"); return null; } }
Guest
public class Client { public static void main(String[] args) { // L'objet réel que nous devons proxy--Landlord HouseOwner houseOwner = new HouseOwner(); // Nous devons utiliser l'objet réel que nous voulons proxy, nous transmettons cet objet, et finalement, nous appelons ses méthodes à travers cet objet réel InvocationHandler handler = new DynamicProxy(houseOwner); /* * Nous créons notre objet proxy à l'aide de la méthode newProxyInstance de Proxy, voyons ses trois paramètres * Le premier paramètre handler.getClass().getClassLoader() , ici nous utilisons l'objet ClassLoader de la classe handler pour charger notre objet proxy * Le deuxième paramètre realSubject.getClass().getInterfaces(), ici nous fournissons à l'objet proxy les interfaces que l'objet réel implémente, ce qui signifie que je veux proxy l'objet réel, ainsi je peux appeler les méthodes de cet ensemble d'interfaces * Le troisième paramètre handler, ici nous avons associé cet objet proxy à l'objet InvocationHandler mentionné ci-dessus */ RentHouse rentHouse = (RentHouse) Proxy.newProxyInstance(handler.getClass().getClassLoader(), houseOwner .getClass().getInterfaces(), handler);//Une classe de proxy dynamique, l'intermédiaire System.out.println(rentHouse.getClass().getName()); rentHouse.rent(); rentHouse.charge("10000"); } }
Regardons maintenant la sortie
com.sun.proxy.$Proxy0 before rent house Méthode:rent Je veux louer ma maison after rent house before charge house Méthode:charge Vous obtenez : 10000 RMB HouseCharge. I will get 100 RMB ProxyCharge. after charge house Processus terminé avec le code de sortie 0
Dans la sortie, il y a before rent house et after rent house, ce qui signifie que nous pouvons ajouter des opérations avant et après la méthode. Regardons également la sortie I will get 100 RMB ProxyCharge. Le frais d'intermédiaire a été perçu10Aucun frais d'intermédiaire de 0, ce qui signifie que nous pouvons non seulement ajouter des opérations, mais aussi remplacer cette méthode ou même empêcher cette méthode d'être exécutée directement.
Au début, lorsque vous examinez le code, vous pourriez avoir beaucoup de doutes. Nous allons voir comment utiliser le proxy dynamique à travers le contenu suivant.
Comment utiliser le proxy dynamique
Dans le mécanisme de proxy dynamique de Java, il y a deux classes et interfaces importantes, l'une est InvocationHandler (Interface), l'autre est Proxy (Class), ces classes et interfaces sont nécessaires pour réaliser notre proxy dynamique.
Chaque classe proxy dynamique doit implémenter l'interface InvocationHandler (médiateur dans le code), et chaque instance de la classe proxy est associée à un handler, lorsque nous appelons une méthode par l'intermédiaire de l'objet proxy, l'appel de cette méthode est redirigé vers la méthode invoke de l'interface InvocationHandler (l'amélioration des méthodes est écrite ici).
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
Nous voyons que cette méthode accepte trois paramètres, alors que représentent ces trois paramètres ?
Object invoke(Object proxy, Method method, Object[] args) throws Throwable //proxy: ils représentent l'objet réel que nous proxyons //method: ils représentent l'objet Method que nous appelons sur l'objet réel //args: ils représentent les paramètres reçus lors de l'appel d'une méthode d'un objet réel
Nous allons maintenant voir la classe Proxy
public static Object newProxyInstance(ClassLoader loader, Class<63;]> interfaces, InvocationHandler h) throws IllegalArgumentException
La classe Proxy a pour objectif de créer un objet proxy dynamique, elle fournit de nombreux méthodes, mais nous utilisons le plus souvent newProxyInstance cette méthode :
public static Object newProxyInstance(ClassLoader loader, Class<63;]> interfaces, InvocationHandler h) throws IllegalArgumentException
L'objet de cette méthode est d'obtenir un objet proxy dynamique, qui reçoit trois paramètres, regardons ce que représentent ces trois paramètres
public static Object newProxyInstance(ClassLoader loader, Class<63;]> interfaces, InvocationHandler h) throws IllegalArgumentException //loader: un objet ClassLoader, définissant par quel objet ClassLoader l'objet proxy généré sera chargé //interfaces: un tableau d'objets Interface, représentant les interfaces que je vais fournir aux objets nécessitant un proxy, si j'apporte un ensemble d'interfaces, l'objet proxy déclare alors qu'il implémente cette interface (polymorphisme), ainsi je peux appeler les méthodes de cet ensemble d'interfaces //h : un objet InvocationHandler, qui représente que lorsque j'appelle cette méthode de l'objet proxy dynamique, il sera lié à quel objet InvocationHandler
De cette manière, en combinant le code fourni ci-dessus, nous pouvons comprendre la méthode d'utilisation du proxy dynamique
Les limites du proxy dynamique
De l'utilisation de la méthode de proxy dynamique, nous voyons en fait que tous les méthodes qui peuvent être renforcées sont implémentées par des interfaces (les méthodes public qui ne réalisent pas l'interface peuvent également être utilisées en héritant de la classe d'agent), dans le code, HouseOwner hérite de RentHouse. Quant aux méthodes privées, le proxy dynamique de JDK est impuissant !
Les proxies dynamiques mentionnés ci-dessus sont ceux de JDK, pour les projets java, il y a également le célèbre CGLib, mais malheureusement, CGLib ne peut pas être utilisé sur Android, le virtuel machine d'Android est différent du JVM.
Conclusion
L'utilisation de proxy dynamique ne s'arrête pas à cela, le principe interne sera présenté dans les articles à venir, mais le mécanisme de génération temporaire de classes d'agent par reflection application class décide qu'il aura un certain impact sur les performances. Cet article en tant que préalable à la principe de retrofit n'est pas trop détaillé, et bienvenue à corriger les omissions et les erreurs !
C'est tout pour cet article. J'espère que cela aidera à votre apprentissage et que vous soutenirez également le tutoriel d'alarme.
Déclaration : le contenu de cet article est tiré du réseau, et les droits d'auteur appartiennent aux propriétaires respectifs. Le contenu est apporté par les utilisateurs d'Internet et téléversé spontanément. Ce site ne possède pas de propriété, n'a pas été traité par l'homme, et n'assume aucune responsabilité juridique. Si vous trouvez du contenu suspect de droits d'auteur, veuillez envoyer un e-mail à : notice#w pour signaler, et fournir des preuves pertinentes.3Déclaration : le contenu de cet article est tiré du réseau, et les droits d'auteur appartiennent aux propriétaires respectifs. Le contenu est apporté par les utilisateurs d'Internet et téléversé spontanément. Ce site ne possède pas de propriété, n'a pas été traité par l'homme, et n'assume aucune responsabilité juridique. Si vous trouvez du contenu suspect de droits d'auteur, veuillez envoyer un e-mail à : notice#w pour signaler, et fournir des preuves pertinentes. Une fois confirmé, ce site supprimera immédiatement le contenu présumé enfreindre les droits d'auteur.