English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Retrofit è un framework di richiesta di rete con un alto grado di decoupling, recentemente ho scoperto questa tecnologia molto potente e pratica chiamata proxy dinamico mentre stavo studiando. Questo articolo sarà un'informazione preliminare su retrofit, in modo che possiate conoscere: quali sono le applicazioni del proxy dinamico, cos'è il proxy dinamico, come utilizzarlo e dove si trovano le sue limitazioni?
Applicazioni del proxy dinamico
1. AOP - programmazione orientata agli aspect, decoupling del programma
In breve, quando si desidera eseguire alcune operazioni comuni prima e dopo i metodi interni di alcune classi, e quando si desidera eseguire operazioni personalizzate nei metodi stessi - utilizzare il proxy dinamico. In presenza di un grande volume di lavoro, è possibile ridurre la quantità di codice e migliorare la manutenibilità.
2. Voglio personalizzare alcuni metodi di una libreria di terze parti
Ho citato una libreria di terze parti, ma alcuni dei suoi metodi non soddisfano le mie esigenze. Voglio riscrivere quei metodi da solo o aggiungere alcune operazioni speciali prima e dopo i metodi - utilizzando il proxy dinamico. Tuttavia, è necessario notare che questi metodi hanno limitazioni, lo spiegherò più tardi.
什么是动态代理
以上的图太过于抽象,我们从生活中的例子开始切入。
假如你是一个大房东(被代理人),你有很多套房子想要出租,而你觉得找租客太麻烦,不愿意自己弄,因而你找一个人来代理你(代理人),帮打理这些东西,而这个人(代理人也就是中介)在帮你出租房屋的时候对你收取一些相应的中介费(对房屋出租的一些额外操作)。对于租客而言,中介就是房东,代理你做一些事情。
以上,就是一个代理的例子,而他为什么叫动态代理,“动态”两个字体现在什么地方?
我们可以这样想,如果你的每一套房子你都请一个代理人帮你打理,每当你想再出租一套房子的时候你得再请一个,这样你会请很多的代理人,花费高额的中介成本,这可以看作常说的“静态代理”。
但假如我们把所有的房子都交给一个中介来代理,让他在多套房子之间动态的切换身份,帮你应付每一个租客。这就是一个“动态代理”的过程。动态代理的一大特点就是编译阶段没有代理类在运行时才生成代理类。
我们用一段代码来看一下
房屋出租的操作
/** *定义一个接口 **/ public interface RentHouse { void rent();//房屋出租 void charge(String str);//出租费用收取 }
proprietario
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."); } }
agenzia immobiliare
public class DynamicProxy implements InvocationHandler { // 这个就是我们要代理的真实对象,即房东 private Object subject; // 构造方法,给我们要代理的真实对象赋初值 public DynamicProxy(Object subject) { this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Possiamo aggiungere alcune operazioni proprie prima dell'agente reale, l'agente riceve la Commissione System.out.println("before " + method.getName() + " house"); System.out.println("Method:" + method.getName()); // Se il metodo è charge, l'agente riceve 100 yuan di Commissione if (method.getName().equals("charge")) { method.invoke(subject, args); System.out.println("Otterrò 100 RMB di Commissione."); } else { // Quando l'oggetto proxy chiama il metodo dell'oggetto reale, viene automaticamente reindirizzato al metodo invoke dell'oggetto handler associato per la chiamata method.invoke(subject, args); } // Possiamo aggiungere alcune operazioni proprie dopo l'agente reale System.out.println("after " + method.getName() + " house"); return null; } }
ospite
public class Client { public static void main(String[] args) { // L'oggetto reale che vogliamo代理 è l'inquilino HouseOwner houseOwner = new HouseOwner(); // Passiamo l'oggetto reale che vogliamo代理 a questa funzione, e infine chiamiamo i suoi metodi tramite questo oggetto reale InvocationHandler handler = new DynamicProxy(houseOwner); /* * Creiamo il nostro oggetto proxy utilizzando il metodo newProxyInstance di Proxy e vediamo i suoi tre parametri * Il primo parametro handler.getClass().getClassLoader() utilizza l'oggetto ClassLoader della classe handler per caricare il nostro oggetto proxy * Il secondo parametro realSubject.getClass().getInterfaces(), in questo caso forniamo all'oggetto proxy l'interfaccia eseguita dall'oggetto reale, il che significa che sto代理 il questo oggetto reale, così posso chiamare i metodi di questo set di interfacce * Il terzo parametro handler, in questo caso associamo l'oggetto proxy all'oggetto InvocationHandler in alto */ RentHouse rentHouse = (RentHouse) Proxy.newProxyInstance(handler.getClass().getClassLoader(), houseOwner .getClass().getInterfaces(), handler);//Una classe di proxy dinamico, agente System.out.println(rentHouse.getClass().getName()); rentHouse.rent(); rentHouse.charge("10000"); } }
Guardiamo l'uscita
com.sun.proxy.$Proxy0 before rent house Method:rent Voglio affittare la mia casa after rent house before charge house Method:charge Ti spetta: 10000 RMB HouseCharge. I will get 100 RMB ProxyCharge. after charge house Processo finito con codice di uscita 0
Nella uscita ci sono before rent house e after rent house, il che significa che possiamo aggiungere operazioni prima e dopo il metodo. Guarda anche l'uscita I will get 100 RMB ProxyCharge. La agenzia ha收取 100 yuan di tassa di agenzia, il che significa che non solo possiamo aggiungere operazioni, ma possiamo anche sostituire il metodo o farlo eseguire direttamente.
All'inizio, guardando il codice, potresti avere molte domande, esaminiamo i seguenti contenuti per vedere come utilizzare il proxy dinamico.
Come utilizzare il proxy dinamico
Nel meccanismo di代理 dinamico di Java, ci sono due classi e interfacce importanti, una è InvocationHandler (Interface), l'altra è Proxy (Class), queste due classi e interfacce sono necessarie per implementare il nostro代理 dinamico.
Ogni classe proxy dinamica deve implementare l'interfaccia InvocationHandler (mediatore nel codice), e ogni istanza di classe proxy è associata a un handler, quando chiamiamo un metodo tramite l'oggetto proxy, la chiamata del metodo viene inoltrata al metodo invoke dell'interfaccia InvocationHandler (l'incremento di funzionalità del metodo si scrive qui).
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
Vediamo che questo metodo accetta tre parametri, allora cosa rappresentano questi tre parametri?
Object invoke(Object proxy, Method method, Object[] args) throws Throwable //proxy: indica l'oggetto reale che stiamo代理 //method: indica l'oggetto Method che rappresenta il metodo che vogliamo chiamare dell'oggetto reale //args: indica i parametri accettati quando si chiama un metodo di un oggetto reale
Prossimamente, diamo un'occhiata alla classe Proxy
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
La classe Proxy serve per creare dinamicamente un oggetto proxy, fornisce molti metodi, ma quelli che usiamo di più sono newProxyInstance:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
Il ruolo di questo metodo è ottenere un oggetto proxy dinamico, che accetta tre parametri, diamo un'occhiata al significato di questi tre parametri
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException //loader: un oggetto ClassLoader, che definisce quale oggetto ClassLoader caricherà l'oggetto proxy generato //interfaces: un array di oggetti Interface, che rappresenta le interfacce che fornirò agli oggetti che devo代理, se fornisco un insieme di interfacce, l'oggetto proxy dichiarerà di implementare l'interfaccia (polimorfismo), così potrò chiamare i metodi di questo insieme di interfacce //h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
//h: un oggetto InvocationHandler, che rappresenta il fatto che quando questo oggetto proxy dinamico chiama un metodo, verrà associato a quale oggetto InvocationHandler
In questo modo, combinando il codice fornito sopra, possiamo capire come utilizzare il proxy dinamico
Limitazioni del proxy dinamico
Dalla guida all'uso del proxy dinamico vediamo che possono essere migliorati i metodi sono implementati tramite proxy (i metodi public non implementati tramite proxy possono essere utilizzati attraverso l'ereditarietà della classe proxy), nel codice HouseOwner eredita RentHouse. Per i metodi private, il proxy dinamico di JDK non può fare nulla!
Conclusione
Le scenari di utilizzo dell'proxy dinamico vanno oltre questi, i principi interni saranno illustrati in articoli futuri, ma il meccanismo di generazione temporanea di classi代理 attraverso la reflection di classe applicativa determina che avrà un impatto sul prestazioni. Questo articolo come articolo preparatorio per il principio di retrofit non è troppo dettagliato, benvenuti a correggere errori e omissioni!
Questo è tutto il contenuto dell'articolo, spero che sia utile per la tua apprendimento e che tu sostenga fortemente la guida a urla.
Dichiarazione: il contenuto di questo articolo è stato tratto da Internet, il copyright è dell'autore originale, il contenuto è stato contribuito autonomamente dagli utenti di Internet e caricato autonomamente, il sito web non detiene i diritti di proprietà, non è stato editato manualmente e non assume responsabilità legali correlate. Se trovi contenuti sospetti di violazione del copyright, sei invitato a inviare una e-mail a notice#oldtoolbag.com (sostituisci # con @ quando invii l'e-mail) per segnalare il problema e fornire prove pertinenti. Una volta verificata, il sito web eliminerà immediatamente i contenuti sospetti di violazione del copyright.