Proxy dinámico JAVA
modo proxy
El patrón de agente es un patrón de diseño de Java de uso común. Su característica es que la clase de agente y la clase delegada tienen la misma interfaz. La clase de agente es principalmente responsable de preprocesar mensajes para la clase delegada, filtrar mensajes y reenviar mensajes a la clase delegada. y procesar mensajes posteriormente. Por lo general, existe una asociación entre una clase de proxy y una clase delegada. Un objeto de una clase de proxy está asociado con un objeto de una clase delegada. El objeto de la clase de proxy en sí no implementa el servicio, sino que llama a los métodos relevantes. del objeto de la clase delegada Proporcionar servicios específicos.
Según el período de creación del agente, la clase de agente se puede dividir en dos tipos.
Proxy estático: creado por programadores o generado automáticamente por una herramienta específica y luego compilado. Antes de ejecutar el programa, el archivo .class de la clase proxy ya existe.
Proxy dinámico: creado dinámicamente utilizando el mecanismo de reflexión cuando el programa se está ejecutando.
Primero eche un vistazo al proxy estático:
1.Contar.java
Copie el código de código de la siguiente manera:
paquete net.battier.dao;
/**
* Definir una interfaz de cuenta
*
* @autor Administrador
*
*/
interfaz pública Cuenta {
// Ver método de cuenta
consulta nula públicaCount();
//Modificar método de cuenta
actualización nula públicaCount();
}
2. CountImpl.java
Copie el código de código de la siguiente manera:
paquete net.battier.dao.impl;
importar net.battier.dao.Count;
/**
* Clase delegada (incluida la lógica empresarial)
*
* @autor Administrador
*
*/
la clase pública CountImpl implementa Count {
@Anular
consulta vacía públicaCount() {
System.out.println("Ver método de cuenta...");
}
@Anular
actualización pública vacíaCount() {
System.out.println("Modificar método de cuenta...");
}
}
CountProxy.java
paquete net.battier.dao.impl;
importar net.battier.dao.Count;
/**
* Esta es una clase proxy (clase de implementación CountImpl mejorada)
*
* @autor Administrador
*
*/
la clase pública CountProxy implementa Count {
privado CountImpl countImpl;
/**
* Anular el constructor predeterminado
*
* @param countImpl
*/
público CountProxy (CountImpl countImpl) {
this.countImpl = contarImpl;
}
@Anular
consulta vacía públicaCount() {
System.out.println("Antes del procesamiento de la transacción");
// Llama al método de la clase delegada;
countImpl.queryCount();
System.out.println("Después del procesamiento de la transacción");
}
@Anular
actualización pública vacíaCount() {
System.out.println("Antes del procesamiento de la transacción");
// Llama al método de la clase delegada;
countImpl.updateCount();
System.out.println("Después del procesamiento de la transacción");
}
}
3. TestCount.java
Copie el código de código de la siguiente manera:
paquete net.battier.test;
importar net.battier.dao.impl.CountImpl;
importar net.battier.dao.impl.CountProxy;
/**
*Clase de recuento de pruebas
*
* @autor Administrador
*
*/
clase pública TestCount {
público estático vacío principal (String [] argumentos) {
CountImpl countImpl = nuevo CountImpl();
CountProxy countProxy = nuevo CountProxy(countImpl);
countProxy.updateCount();
countProxy.queryCount();
}
}
Al observar el código, se puede encontrar que cada clase de proxy solo puede servir a una interfaz. De esta manera, inevitablemente se generarán demasiados proxy durante el desarrollo del programa. Además, todas las operaciones de proxy son las mismas excepto el método que llaman. debe repetirse en este momento. La mejor manera de resolver este problema es usar una clase de proxy para completar todas las funciones de proxy. En este caso, se debe usar un proxy dinámico para completarlo.
Echemos un vistazo al proxy dinámico:
El proxy dinámico JDK contiene una clase y una interfaz:
Interfaz de controlador de invocación:
interfaz pública InvocationHandler {
invocación pública de objeto (proxy de objeto, método de método, argumentos de objeto []) lanza Throwable;
}
Descripción del parámetro:
Proxy de objeto: se refiere al objeto que se está representando.
Método de método: el método que se llamará.
Object[] args: parámetros necesarios al llamar al método
Puede pensar en una subclase de la interfaz InvocationHandler como la clase de operación final de un proxy, reemplazando a ProxySubject.
Clase de proxy:
La clase Proxy es una clase que se especializa en operaciones de proxy. Esta clase se puede utilizar para generar dinámicamente clases de implementación para una o más interfaces. Esta clase proporciona los siguientes métodos de operación:
Objeto estático público newProxyInstance (cargador ClassLoader, interfaces Class<?>[],
Controlador de invocación h)
lanza IllegalArgumentException
Descripción del parámetro:
Cargador ClassLoader: cargador de clases
Clase<?>[] interfaces: obtener todas las interfaces
InvocationHandler h: obtiene la instancia de subclase de la interfaz InvocationHandler
Ps: cargador de clases
Se requiere una instancia de la clase ClassLoader en el método newProxyInstance () en la clase Proxy. En realidad, hay tres cargadores de clases principales en Java;
Booststrap ClassLoader: este cargador está escrito en C++ y no se puede ver en el desarrollo general;
Extension ClassLoader: se utiliza para cargar clases de extensión, generalmente correspondientes a clases en el directorio jre/lib/ext;
AppClassLoader: (predeterminado) carga la clase especificada por classpath, que es el cargador más utilizado.
proxy dinámico
A diferencia de la clase de proxy estática, existe la clase de proxy dinámico. El código de bytes de la clase de proxy dinámico se genera dinámicamente mediante el mecanismo de reflexión de Java cuando el programa se está ejecutando, sin la necesidad de que los programadores escriban manualmente su código fuente. Las clases de proxy dinámico no solo simplifican el trabajo de programación, sino que también mejoran la escalabilidad de los sistemas de software, porque el mecanismo de reflexión de Java puede generar cualquier tipo de clase de proxy dinámico. La clase Proxy y la interfaz InvocationHandler en el paquete java.lang.reflect brindan la capacidad de generar clases de proxy dinámicas.
Ejemplo de proxy dinámico:
1.BookFacade.java
Copie el código de código de la siguiente manera:
paquete net.battier.dao;
interfaz pública BookFacade {
addBook vacío público();
}
2.BookFacadeImpl.java
Copie el código de código de la siguiente manera:
paquete net.battier.dao.impl;
importar net.battier.dao.BookFacade;
la clase pública BookFacadeImpl implementa BookFacade {
@Anular
addBook vacío público() {
System.out.println("Agregar método de libro...");
}
}
LibroFacadeProxy.java
paquete net.battier.proxy;
importar java.lang.reflect.InvocationHandler;
importar java.lang.reflect.Method;
importar java.lang.reflect.Proxy;
/**
* Clase de proxy de proxy dinámico JDK
*
* @autor estudiante
*
*/
la clase pública BookFacadeProxy implementa InvocationHandler {
objetivo de objeto privado;
/**
* Vincula el objeto delegado y devuelve una clase de proxy
* objetivo @param
* @devolver
*/
Enlace de objeto público (objeto objetivo) {
this.objetivo = objetivo;
//Obtener el objeto proxy
devuelve Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this); //Para vincular la interfaz (esto es un defecto, cglib lo compensa)
}
@Anular
/**
* Método de llamada
*/
Invocación pública de objeto (proxy de objeto, método de método, argumentos de objeto [])
lanza arrojable {
Resultado del objeto = nulo;
System.out.println("La cosa comienza");
//método de ejecución
resultado=método.invoke(destino, argumentos);
System.out.println("Fin de las cosas");
resultado de devolución;
}
}
3. PruebaProxy.java
Copie el código de código de la siguiente manera:
paquete net.battier.test;
importar net.battier.dao.BookFacade;
importar net.battier.dao.impl.BookFacadeImpl;
importar net.battier.proxy.BookFacadeProxy;
clase pública TestProxy {
público estático vacío principal (String [] argumentos) {
Proxy BookFacadeProxy = nuevo BookFacadeProxy();
BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());
libroProxy.addBook();
}
}
Sin embargo, el proxy dinámico de JDK depende de la implementación de la interfaz. Si algunas clases no implementan la interfaz, el proxy JDK no se puede utilizar, por lo que se debe utilizar el proxy dinámico cglib.
Proxy dinámico cglib
El mecanismo de proxy dinámico de JDK solo puede implementar clases que implementan interfaces. Las clases que no pueden implementar interfaces no pueden implementar el proxy dinámico de JDK. Su principio es generar una subclase para la clase de destino especificada y anular los métodos para lograr mejoras. , pero debido a que se utiliza la herencia, la clase modificada final no puede ser representada.
Ejemplo
1.BookFacadeCglib.java
Copie el código de código de la siguiente manera:
paquete net.battier.dao;
interfaz pública BookFacade {
addBook vacío público();
}
2.BookCadeImpl1.java
Copie el código de código de la siguiente manera:
paquete net.battier.dao.impl;
/**
* Esta es una clase de implementación que no implementa la interfaz.
*
* @autor estudiante
*
*/
clase pública BookFacadeImpl1 {
addBook vacío público() {
System.out.println("Método común para agregar libros...");
}
}
3.BookFacadeProxy.java
Copie el código de código de la siguiente manera:
paquete net.battier.proxy;
importar java.lang.reflect.Method;
importar net.sf.cglib.proxy.Enhancer;
importar net.sf.cglib.proxy.MethodInterceptor;
importar net.sf.cglib.proxy.MethodProxy;
/**
* Utilice el proxy dinámico cglib
*
* @autor estudiante
*
*/
la clase pública BookFacadeCglib implementa MethodInterceptor {
objetivo de objeto privado;
/**
* Crear objeto proxy
*
* objetivo @param
* @devolver
*/
objeto público getInstance (objeto objetivo) {
this.objetivo = objetivo;
Potenciador potenciador = nuevo potenciador();
Enhancer.setSuperclass(this.target.getClass());
// método de devolución de llamada
potenciador.setCallback(esto);
//Crear objeto proxy
return potenciador.create();
}
@Anular
// método de devolución de llamada
intercepción de objeto público (Objeto obj, Método método, Objeto [] args,
Proxy MethodProxy) lanza Throwable {
System.out.println("La cosa comienza");
proxy.invokeSuper(obj, argumentos);
System.out.println("Fin de las cosas");
devolver nulo;
}
}
4. PruebaCglib.java
Copie el código de código de la siguiente manera:
paquete net.battier.test;
importar net.battier.dao.impl.BookFacadeImpl1;
importar net.battier.proxy.BookFacadeCglib;
clase pública TestCglib {
público estático vacío principal (String [] argumentos) {
LibroFacadeCglib cglib=nuevo LibroFacadeCglib();
BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1());
libroCglib.addBook();
}
}