Conceptos básicos: requiere ideas de diseño orientadas a objetos, ideas polimórficas e ideas de reflexión;
La aparición del mecanismo de proxy dinámico Java permite a los desarrolladores de Java obtener dinámicamente clases proxy sin tener que escribir manualmente clases de proxy. La clase proxy es responsable de enviar todas las llamadas de método al objeto delegado para reflejar la ejecución. Durante el proceso de ejecución de despacho, los desarrolladores también pueden ajustar el objeto delegado y sus funciones según sea necesario. Este es un marco proxy muy flexible y flexible. Al leer este artículo, los lectores tendrán una comprensión más profunda del mecanismo de proxy dinámico Java. Este artículo analiza primero el código basado en el mecanismo operativo y las características del proxy dinámico Java y deduce la implementación interna de las clases de generación dinámica.
Conceptos básicos y clasificación del modelo de agente
Modo proxy: proporciona un proxy para otros objetos para controlar el acceso a este objeto. El objeto proxy actúa como un intermediario y puede eliminar servicios o agregar servicios adicionales, o citar a otros: "La clase proxy es responsable de los mensajes de preprocesamiento para la clase delegada, filtrando mensajes y mensajes de reenvío, y realiza un procesamiento posterior después de que la clase delegada ejecute el mensaje".
Escenarios de aplicación del modo de agente en el desarrollo
Proxy remoto: proporciona objetos representativos de LAN para objetos de diferentes regiones geográficas.
Agente virtual: retrase los objetos que consumen muchos recursos según sea necesario y cree cuando realmente sean necesarios. Por ejemplo, el texto se muestra primero y luego la imagen se muestra en la página web.
Agente de protección: controla los derechos de acceso de diferentes usuarios. Por ejemplo: solo después de que el registro del cliente sea exitoso puede agregar, eliminar, modificar y verificar las operaciones.
Agente de referencia inteligente: proporciona servicios adicionales al agente objetivo.
Cómo implementar el modo proxy
¡Cuál es mejor implementar proxy dinámico utilizando herencia y agregación!
interfaz public moverable {public void Move ();} public class Car implementa mudable {@Override public void Move () {try {Thread.sleep (new Random (). NextInt (1000)); System.out.Println ("... conducir ...");} Catch (interruptedEdEdException e) {// ado CAR2 extiende el CAR {@Override public void Move () {// separa el código, aumenta la lógica de negocios larga inicio = system.currentTimemillis (); system.out.println ("El Car comienza a impulsar ..."); super.move (); longtime = system.currentTimemillis (); system.println ("el carro de carro ... TIEMPLE: TIEMPLE: TIEMPLE: TIEMPLE: TIEMPLE: TIEMPLO: TIEMPLO: TIEMPLO: TIEMPLO: TIEMPO: TIEMPO: TIEMPLO: TIEMPO: TIEMPLO: TIEMPO: TIEMPLO: TIEMPLO: TIEMPLO "+(endtime-starttime)+" ms ");}}Método de herencia para implementar proxy
Moveablecar2=newCar2();
car2.move();
El método de agregación implementa proxy
Carcar=newCar();
Moveablem=newCar3(car);
m.move();
Resumir
El método de herencia no es lo suficientemente flexible. Cuando las funciones se superponen, solo puede expandir la clase de proxy sin bloques;
Usando la agregación, los agentes pueden transmitirse entre sí y un proxy puede combinarse de manera flexible;
La clase pública CarlogProxy extiende CAR {@Override public void Move () {// separa el código y aumenta la lógica empresarial Long Starttime = System.CurrentTimemillis (); System.out.println ("Login Start ..."); Super.move (); Long EndTime = System.CurrentNemEmiLis (); System.out.println ("Login End ...");});};};};} CartimeProxy implementa mudible {public startimeProxy (car car) {super (); this.car = car;} private carcar; @Override public void Move () {// separa el código y agrega la lógica de negocios Long Starttime = System.CurrentTimillis (); System.Println ("The Car comienza a conducir ..."); CAR.Move ();););); EndTime = System.CurrentTimEmillis (); System.out.println ("El automóvil termina para conducir ... Tiempo:"+(EndTime-starttime)+"MS");}}@Test: Car Car = New Car (); cartelProxy ctp = newtimeProxy (Car); carlogproxy clp = new carlogpoxy (ctp); También pase instancias proxy entre sí a través de interfaces Carlogproxy Clp1 = new CarlogProxy (CAR); CartimeProxy CTP1 = New CarimEproxy (CLP1); CTP1.MOVE ();Proxy dinámico JDK y proxy dinámico CGLIB
JDK proxy dinámico
Implementación de agentes
¿Qué se debe hacer si diferentes objetos quieren implementar la clase proxy con la misma función?
En este momento, puede intentar integrarlo en la misma clase de proxy ------- proxy dinámico: implementación de proxy para diferentes clases/diferentes métodos;
El proceso general es el siguiente:
La clase Java Dynamic Proxy se encuentra debajo del paquete Java.Lang.Reflect, que generalmente involucra principalmente las siguientes dos clases:
(1) InterfaceInVocationHandler: solo se define un método en esta interfaz PublicObjectInvoke (ObjectObj, MethodMethod, Object [] Args)
OBJ: Generalmente se refiere a la clase de poder
Método: es el método proxy
Args es una matriz de parámetros para este método.
Este método abstracto se implementa dinámicamente en la clase proxy.
(2) proxy: esta clase es una clase proxy dinámica
statixObjectnewProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandlerh)
Devuelve una instancia de la clase de glucosí, y la clase proxy devuelta se puede usar como la clase proxy (puede usar el método declarado en la interfaz por la clase proxy);
Ejemplo de implementación:
@ TimeHandler public class TimeHandler implementa InvocationHandler {public TimeHandler (Object Target) {super (); this.target = target;} private objectTarget;/** parámetros:* proxy proxy objeto* método de método de proxy objeto* args parámetro** valor de return:* Object Method Value de retorno*/@ anular objeto público invoke (objeto Object Método, método de método, objeto argS** return Value:* Valor de retorno de objetos* starttime = system.currentTimemillis (); system.out.println ("El automóvil comienza a conducir ..."); método.invoke (target); largo endtime = system.currentTimemillis (); system.out.println ("El automóvil termina para conducir ... Tiempo:"+(tiempo endtime-arranque)+"ms"); return null;}}} @The Interface of the Proxy Class Public Interface Movible {public void Move ();}@la clase proxy El auto de clase pública implementa mudible {@Override public void Move () {try {Thread.sleep (new Random (). NextInt (1000)); System.out.println ("... Driving ...");} Catch (InterruptedException e) {// TODO Generado automático E.PrintStackTrace ();}}}}}}}}}}}}}}}}}}}}}}}}}}}}}@prueba
Prueba de clase pública { / *** JDK Dynamic Proxy Test Clase* / public static void main (string [] args) {car car = new Car (); InvocationHandler H = New TimeHandler (CAR); Clase <?> Cls = car.getClass (); /** cargador de clase cargador* interfaces implementando interfaz* h invocationHandler*/ movible m = (móvil) proxy.newproxyInstance (cls.getClassLoader (), cls.getInterfaces (), h); M.Move (); }}&& Probar resultados
Resumen
El DynamicProxy es una clase así:
Es una clase generada en tiempo de ejecución. Esta clase necesita implementar un conjunto de interfaces. Cuando se usa clases de proxy dinámico, se debe implementar la interfaz InvocationHandler.
Pasos generales para el proxy dinámico JDK
1. Cree una clase que implementa la interfaz InvocationHandler, que debe implementar Invoke ()
2. Cree la clase e interfaz proxy
3. Llame al método estático del proxy para crear una clase proxy
NewProxyInstance (ClassLoaderLoader, Interfaces de clase [], InvocationHandlerh)
4. Llame a los métodos a través del proxy
Implementación del proxy dinámico CGLIB
Implementación de agentes
@Introducting CGLIB-Node-2.2.Jar Paquete
@CglibProxy Intercept Class Implementa el método de interfaz Interescept: Reescribir el método de Intercept
clase pública cglibproxy implementa metodInterceptor {private mejorhancerenHancer = new mejor (); public object getProxy (clase cl) {// Establezca la clase que crea subclass enhancer.setsuperClass (cl); mejor.etancer.setCallback (this); return de return.create ();}/** intercept todos los objetivos de la clase de objetivo* Método Args* instancia proxy de la clase proxy**/@anular el objeto público intercept (object obj, método m, objeto [] args, métodoproxy proxy) lanza shrewable {system.out.println ("login start ..."); // La clase proxy llama a la clase principal el método proxy.invokesuper (obj); system.out.println (");"); "); nulo;}}@Praxy Class Train
Public Class Train {public void Move () {System.out.println ("El tren está conduciendo ..."); }}Clase de @Test
Prueba de clase pública { / *** CGLIBPROXY Dynamic Proxy Test Clase* / public static void main (String [] args) {cglibproxy proxy = new cglibProxy (); Train t = (trenes) proxy.getProxy (Train.class); t.move (); }}## Resultados de la prueba:
Resumen
Pasos generales para implementar proxy dinámico utilizando cglibproxy
1. Cree una clase para implementar el Interface MethodInterceptor y anular el método de Intercept
2. Crea una clase proxy
3. Llame al método personalizado de la clase proxy para obtener una instancia de proxy
4. Llame al método que debe ser ejecutado por la instancia de proxy
Resumen comparativo
JDK proxy dinámico
1. Solo clases proxy que implementan interfaces
2. Las clases sin interfaz no pueden implementar proxy dinámico para JDK
Proxy dinámico CGLIB
1. Implementación de proxy para clases
2. Genere una subclase a la clase de destino de ejecución y use el método de interceptación de tecnología para interceptar todas las llamadas de métodos de clase principal.
Simular los pasos de generación de agentes
Ideas:
Función de implementación: devuelva el objeto proxy a través de la nuevainstancia de proxy
1. Declare una pieza de código fuente (agente de generación dinámica)
2. Compile el código fuente (JDKCompilerapi) para generar nuevas clases (clases proxy)
3. Cargue esta clase en la memoria y genere un nuevo objeto (objeto proxy)
4. Devuelve el objeto proxy
Mejorar la implementación de proxy dinámico
Primero, obtenemos el compilador del sistema, obtenemos el administrador de archivos a través del compilador y luego obtenemos el archivo. El compilador realiza la tarea de compilación. Después de completar la compilación, cargamos el archivo de clase en el cargador de clase, obtenemos la instancia a través del método del constructor y luego llamamos a NewInStance () para recibir una instancia de un objeto.
(1) Obtenga el compilador javacompilerCompiler = ToolProvider.getSystemJavacOpmiler ();
(2) Administrador de archivos StandardJavafilemanagerFilemgr = compiler.getStandardFilemanager (NULL, NULL, NULL);
(3) Obtenga el archivo ITerableUnits = filemgr.getJavafileObjects (nombre de archivo);
(4) Tarea de compilación CompilationTaskt = Compiler.getTask (Null, Filemgr, Null, Null, Null, Null, Unidades);
(5) Cargar a la memoria
ClassLoLoadRCl = classLoCer.getSystemClassLoader ();
Classc = cl.loadclass ("com.imooc.proxy. $ Proxy0");
(6) Construya una instancia a través del constructor del objeto proxy
Constructorctr = c.getConstructor (infcE);
ctr.newinstance (newcar ());
--------
Como se mencionó anteriormente, la lógica comercial interna está codificada. ¿Cómo implementar el proxy dinámico real y la lógica comercial designada dinámicamente?
1. Necesita crear un procesador de transacciones. Primero, crea una interfaz, es decir, InvocationHandler. Para simular JDK, el nombre de la interfaz es el mismo que el nombre del procesador de transacciones JDK. También escribe un método llamado Invoke (), que se utiliza para representar un cierto método de un objeto para el procesamiento de negocios. Por lo tanto, debe pasar un cierto objeto y el método del objeto como parámetros del método Invoke (). Invoke (ObjectObj, MethodMethod), el método utilizado como parámetro para la reflexión de Java, y este paquete debe introducirse. De esta manera, se completa la interfaz Invocathandler.
2. Cree clases de implementación de procesamiento de transacciones, como TimerProxy, para implementar la interfaz InvocationHandler, para que la estructura se convierta en
"―Iar "" ..... ... ..... ... ..... .....lo. "" ..... .....lo.
Debe pasar el objeto de destino. Si no tiene parámetros, no puede escribir parámetros. Cree un método de construcción de objetos proxy e inicialice el objeto de destino.
3. En el método NewProxyInStance () de la clase proxy, además de usar la interfaz de clase de destino como parámetro, también debe pasar el InvocationHandler del procesador de transacciones y luego cambiar la parte codificada del objeto de instancia creado y usar el método del procesador de transacciones para reemplazarlo. La dificultad radica en el empalme de las cuerdas.
Resumir
En nuestro proyecto, el patrón de agente tiene su propio significado práctico. Por ejemplo, si queremos llamar a una clase bajo cierto paquete JAR, podemos agregar una lógica comercial especial antes de llamar a esta clase. Este método también se llama programación orientada a AOP. (Agregue funciones adicionales sin cambiar las funciones originales).
Lo anterior es toda la explicación detallada del código Java Dynamic Proxy (Patrón de diseño) En este artículo, espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a otros temas relacionados en este sitio. Si hay alguna deficiencia, deje un mensaje para señalarlo. ¡Gracias amigos por su apoyo para este sitio!