Si la clase proxy ya existe antes de que se ejecute el programa, entonces este método de proxy se llama proxy estático. En este caso, la clase proxy generalmente se define en el código Java. Normalmente, la clase de proxy y la clase delegada en el proxy estático implementan la misma interfaz o se derivan de la misma clase principal.
1. Descripción general
1. ¿Qué es un agente?
Todos sabemos que los agentes de WeChat simplemente están vendiendo productos en nombre de los fabricantes, y el fabricante "confió" a los agentes para venderlos. Con respecto a los agentes comerciales de WeChat, en primer lugar, cuando les compramos cosas, generalmente no sabemos quién es el fabricante, es decir, el "Comisionado" es invisible para nosotros; En segundo lugar, los agentes comerciales de WeChat se dirigen principalmente a las personas en el círculo de amigos como sus clientes, lo cual es equivalente a un "filtro" del grupo de clientes para el fabricante. Afrazamos aún más el agente y el fabricante de micro-negocios. El primero puede abstraerse como una clase de agente, y el segundo puede abstraerse como una clase delegada (clase de agente). Al usar un proxy, generalmente hay dos ventajas y puede corresponder a las dos características del agente de micro-negocio que mencionamos:
Ventaja 1: puede ocultar la implementación de la clase delegada;
Ventaja 2: puede lograr el desacoplamiento entre el cliente y la clase delegada, y puede hacer un procesamiento adicional sin modificar el código de clase delegado.
2. Proxy estático
Si la clase proxy ya existe antes de que se ejecute el programa, entonces este método de proxy se llama proxy estático. En este caso, la clase proxy generalmente se define en el código Java. Normalmente, la clase de proxy y la clase delegada en el proxy estático implementan la misma interfaz o se derivan de la misma clase principal. A continuación, utilizamos la clase de proveedores para representar al fabricante y la clase de BusinessAgent para representar al agente de micro-negocios para introducir la simple implementación de agentes estáticos. Tanto la clase de delegación como la clase proxy implementan la interfaz de venta. La definición de la interfaz de venta es la siguiente:
interfaz pública vender {void sell (); void ad (); } La definición de la clase de proveedor es la siguiente: el proveedor de la clase pública implementa vender {public void sell () {System.out.println ("en el método de venta"); } public void ad () {System, out.println ("AD Method")}} La definición de la clase proxy BusinessAgent es la siguiente:
El proveedor de clase pública implementa vender {public void sell () {System.out.println ("en el método de venta"); } public void ad () {System, out.println ("AD Method")}} A partir de la definición de la clase BusinessAgent, podemos entender que los agentes estáticos se pueden implementar mediante agregación, de modo que la clase de agente pueda tener una referencia a la clase delegada.
Consideremos este requisito a continuación: agregue una función de filtrado a la clase de proveedores y vendamos bienes solo a estudiantes universitarios. A través del proxy estático, podemos lograrlo sin modificar el código de la clase de proveedores. Solo necesitamos agregar un juicio al método de venta en la clase BusinessAgent y puede ser el siguiente:
public class BusinessAgent Implements sell {... public void sell () {if (isCollegestudent ()) {Vendor.sell (); }} ...} Esto corresponde a la segunda ventaja de usar un proxy mencionado anteriormente: puede lograr el desacoplamiento entre el cliente y la clase delegada, y puede hacer un procesamiento adicional sin modificar el código de clase delegado. La limitación del proxy estático es que debe escribir una clase de proxy antes de ejecutarse. Centrémonos en introducir el método proxy dinámico para generar clases de proxy en tiempo de ejecución.
2. Agente dinámico
1. ¿Qué es proxy dinámico?
El método proxy creado por la clase proxy cuando se ejecuta el programa se llama proxy dinámico. Es decir, en este caso, la clase proxy no se define en el código Java, pero se genera dinámicamente en tiempo de ejecución en función de nuestras "instrucciones" en el código Java. En comparación con el proxy estático, la ventaja del proxy dinámico es que puede manejar fácilmente las funciones de la clase proxy de manera uniforme sin modificar las funciones de cada clase de proxy. Esto es más abstracto. Combinemos un ejemplo para introducir cómo se reflejan las ventajas del proxy dinámico.
Ahora, supongamos que queremos implementar el requisito: salida "antes" antes de ejecutar el método en la clase delegada y la salida "después de" después de ejecutar. Presentaremos a la clase de proveedores como la clase delegada en el ejemplo anterior y la clase BusinessAgent como la clase proxy. Primero, usemos un proxy estático para lograr este requisito. El código relevante es el siguiente:
Public Class BusinessAgent Implements Sell {privado proveedor de proveedores; Public BusinessAgent (proveedor de proveedores) {this.mvendor = proveedor; } public void sell () {System.out.println ("antes"); mvendor.sell (); System.out.println ("después"); } public void ad () {System.out.println ("antes"); mvendor.ad (); System.out.println ("después"); }} En el código anterior, podemos entender que la implementación de nuestras necesidades a través del proxy estático requiere que agregemos la lógica correspondiente a cada método. Aquí solo hay dos métodos, por lo que la carga de trabajo no es grande. ¿Qué pasa si la interfaz de venta contiene cientos de métodos? En este momento, el uso de proxy estático escribirá mucho código redundante. Al usar proxy dinámico, podemos hacer una "indicación uniforme" para procesar uniformemente todos los métodos de las clases de proxy sin modificar cada método uno por uno. Presentemos cómo usar proxy dinámico para implementar nuestras necesidades.
2. Use proxy dinámico
(1) Al usar proxy dinámico en la interfaz InvocationHandler, necesitamos definir una clase intermediaria ubicada entre la clase proxy y la clase delegada. Esta clase intermedia es necesaria para implementar la interfaz InvocationHandler. La definición de esta interfaz es la siguiente:
Interfaz pública InvocationHandler {Object Invoke (Object proxy, método método, objeto [] args); } Desde el nombre InvocationHandler, podemos saber que la clase de mediación que implementa esta interfaz se usa como "procesador de llamadas". Cuando llamamos al método del objeto de clase proxy, esta "llamada" se reenviará al método de invoke. El objeto de clase proxy se pasa como parámetro proxy. El método de parámetro identifica qué método llamamos la clase proxy. Args es el parámetro de este método. De esta manera, nuestras llamadas a todos los métodos en la clase proxy se convertirán en llamadas para invocar, por lo que podemos agregar una lógica de procesamiento unificada al método de invocación (o diferentes métodos de la clase proxy se pueden procesar de acuerdo con los parámetros del método). Por lo tanto, solo necesitamos emitir "antes" en la implementación del método de invocación de la clase de mediación, luego llamar al método de invocación de la clase delegada y luego salir "después". Implementemos paso a paso.
(2) Bajo el método de proxy dinámico de la clase delegada, la clase delegada debe implementar una interfaz determinada. Aquí implementamos la interfaz de venta. La definición de la clase de proveedores es la siguiente:
El proveedor de clase pública implementa vender {public void sell () {System.out.println ("en el método de venta"); } public void ad () {System, out.println ("AD Method")}} (3) Clase de mediación Como se mencionó anteriormente, la clase de mediación debe implementar la interfaz InvocationHandler, ya que el procesador de llamadas "intercepta" las llamadas a los métodos de clase proxy. La definición de la clase intermedia es la siguiente:
clase pública DynamicProxy implementa InvocationHandler {objero privado obj; // obj es un objeto de clase delegada; Public DynamicProxy (object obj) {this.obj = obj; } @Override public Object Invoke (Proxy de objeto, método Método, objeto [] args) lanza lando {system.out.println ("antes"); Resultado del objeto = método.invoke (obj, args); System.out.println ("después"); resultado de retorno; }} En el código anterior, podemos ver que la clase intermediaria contiene una referencia del objeto delegado, y el método correspondiente del objeto delegado se llama en el método Invoke (línea 11). ¿Crees que parece familiar cuando ves esto? Manteniendo la referencia del objeto delegado a través del método de agregación, convirtiendo en última instancia todas las llamadas externas para invocar en llamadas al objeto delegado. ¿No es este un método de implementación de proxy estático que presentamos anteriormente? De hecho, la clase intermedia y la clase delegada forman una relación proxy estática. En esta relación, la clase intermedia es una clase proxy, y la clase delegada es una clase de delegación; La clase proxy y la clase intermedia también forman una relación proxy estática. En esta relación, la clase intermedia es una clase de delegación y la clase proxy es una clase proxy. En otras palabras, la relación dinámica de proxy consiste en dos conjuntos de relaciones proxy estáticas, que es el principio de proxy dinámico. Presentemos cómo "instruir" generar dinámicamente clases proxy.
(4) Class de generación dinámica de generación de generación dinámica Los códigos relevantes de la clase de proxy son los siguientes:
Public Class Main {public static void main (String [] args) {// Cree una instancia de la clase de mediación DynamicProxy inter = new DynamicProxy (new Vendor ()); // Agregar esta oración generará un archivo $ proxy0.class, que es el sistema de archivos de clase proxy generado dinámicamente.getProperties (). Put ("Sun.misc.ProxyGenerator.SaveGeneratedFiles", "True"); // Obtenga la instancia de clase proxy sell sell sell = (sell) (proxy.newproxyinstance (sell.class.getclassloader (), nueva clase [] {sell.class}, inter)); // Llamar al método de clase proxy a través del objeto de clase proxy en realidad irá al método Invoke para llamar a sell.sell (); sell.ad (); }} En el código anterior, llamamos al método NewProxyInstance de la clase proxy para obtener una instancia de clase proxy. Esta clase proxy implementa la interfaz que especificamos y distribuirá llamadas de método al procesador de llamadas especificado. La declaración de este método es la siguiente:
Copie el código de la siguiente manera: Public Static Object NewProxyInstance (ClassLoader Loader, clase <?> [] Interfaces, InvocationHandler h) Lanza ilegalargumentException
Los tres parámetros del método son los siguientes:
cargador: define el clase de clase de la clase proxy;
Interfaces: Lista de interfaces implementadas por la clase proxy
H: Llame al procesador, es decir, la instancia de clase que definimos anteriormente que implementa la interfaz InvocationHandler, ejecutémoslo para ver si nuestro proxy dinámico puede funcionar correctamente. La salida que ejecuto aquí es:
Esto muestra que nuestro proxy dinámico está funcionando.
Hemos mencionado brevemente el principio del proxy dinámico anterior. Aquí resumiremos brevemente: Primero, podemos obtener la instancia de clase Proxy a través del método NewProxyInstance, y luego podemos llamar al método de clase Proxy a través de esta instancia de clase Proxy. En el método de clase proxy, en realidad llamaremos al método de invocación de la clase de mediación (llamada procesador). En el método de Invoke, llamamos al método correspondiente de la clase delegada y podemos agregar nuestra propia lógica de procesamiento.
Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.