Las clases de proxy dinámica de Java se pueden dividir en dos tipos.
Proxy estático: creado por programadores o genera automáticamente el código fuente mediante herramientas específicas y lo compila. Antes de que se ejecute el programa, el archivo .class de la clase proxy ya existe.
Proxy dinámico: se crea dinámicamente utilizando el mecanismo de reflexión cuando el programa se está ejecutando.
1. Primero, demostraremos el proxy dinámico Java.
Ahora tenemos una interfaz comercial simple que dice, como sigue:
La copia del código es la siguiente:
paquete testaop;
interfaz pública diciendo {
public void Sayshello (nombre de cadena);
Public void Talking (nombre de cadena);
}
Una clase de implementación simple que dice Impl, como sigue:
La copia del código es la siguiente:
paquete testaop;
clase pública que dice Implement Dicho {
@Anular
public void sayshello (nombre de cadena) {
// TODO STUB de método generado automático
System.out.println (nombre + ": ¡Hola a todos!");
}
@Anular
Public void Talking (nombre de cadena) {
// TODO STUB de método generado automático
System.out.println (Nombre + ": Quiero decir, ¡debemos trabajar duro para construir una sociedad armoniosa!");
}
}
Lo que queremos lograr es implantar dinámicamente el procesamiento antes y después de decirhello y hablar.
JDK Dynamic Proxy utiliza principalmente dos clases en el paquete java.lang.reflect: proxy e invocationHandler.
InvocationHandler es una interfaz que define la lógica de corte transversal mediante la implementación de esta interfaz y llama al código de la clase de destino a través de un mecanismo de reflexión, teje dinámicamente la lógica transversal y la lógica comercial.
Proxy usa InvocationHandler para crear dinámicamente una instancia que se ajuste a una determinada interfaz y genera un objeto proxy de la clase de destino.
De la siguiente manera, creamos una instancia de Invocathandler:
La copia del código es la siguiente:
paquete testaop;
import java.lang.reflect.invocationHandler;
import java.lang.reflect.method;
clase pública MyInVocationHandler implementa InvocationHandler {
objetivo de objeto privado;
MyInVocationHandler (objetivo de objeto) {
this.target = Target;
}
@Anular
Public Object Invoke (proxy de objeto, método método, objeto [] args)
lanza tirarse {
// ejecutar antes del método de destino
System.out.println ("" ... ... ...
System.out.println ("¡Hable en el escenario siguiente!");
// Llamada del método de destino
Objeco obj = método.Invoke (Target, args);
// Ejecutar el método de destino después
System.out.println ("¡Todos aplauden y estén aliento!");
regresar obj;
}
}
Aquí está la prueba:
La copia del código es la siguiente:
paquete testaop;
import java.lang.reflect.proxy;
clase pública JDKPROXYTEST {
public static void main (string [] args) {
// La categoría de negocios objetivo que desea ser agente
Dicho Target = new dagingImpl ();
// tejer la clase de destino y la clase de corte transversal juntos
MyInVocationHandler Handler = new MyInVocationHandler (Target);
// crear una instancia de proxy
Diciendo proxy = (decir) proxy.newproxyinstance (
Target.getClass (). GetClassLoader (), // El cargador de clase de la clase de destino
Target.getClass (). getInterfaces (), // interfaces de la clase de destino
controlador); // clase transversal
proxy.sayhello ("Xiao Ming");
proxy.talking ("xiaoli");
}
}
La operación es la siguiente:
La copia del código es la siguiente:
".....-- ...
¡Hable en el escenario siguiente persona!
Xiao Ming: ¡Hola a todos!
¡Todos aplaudieron y animaron!
".....-- ...
¡Hable en el escenario siguiente persona!
Xiaoli: Quiero decir, ¡debemos trabajar duro para construir una sociedad armoniosa!
¡Todos aplaudieron y animaron!
Hay una gran limitación para usar el proxy dinámico JDK, que es que requiere que la clase de destino debe implementar la interfaz del método correspondiente, y solo puede crear instancias proxy para la interfaz. Podemos ver en el método de proxy de NewProxyInstance en la clase de prueba anterior que el segundo parámetro de este método es la interfaz de la clase de destino. Si esta clase no implementa una interfaz, depende del proxy dinámico CGLIB.
CGLIB adopta tecnología de bytecode muy subyacente, que puede crear una subclase para una clase y usar técnicas de interceptación de métodos en la subclase para interceptar todas las llamadas de métodos de clase principal e implantar lógica transversal en la situación.
2. A continuación, demostraremos el proxy dinámico CGLIB.
En primer lugar, necesitamos guiar el paquete.
Primero creamos un creador proxy cglibproxy:
La copia del código es la siguiente:
paquete testaop.cglib;
import java.lang.reflect.method;
importar net.sf.cglib.proxy.enhancer;
importar net.sf.cglib.proxy.methodinterceptor;
importar net.sf.cglib.proxy.methodproxy;
clase pública CGLIBPROXY Implementa MethodInterceptor {
Potencador potencador = nuevo mejor ();
objeto público getProxy (class clazz) {
// Establecer la subclase que se creará
mejorar.setsuperClass (Clazz);
potencador.setCallback (esto);
// Crear dinámicamente instancias de subclase a través de la tecnología Bytecode
return mejor.create ();
}
@Anular
Interception Public Object (Object obj, método método, objeto [] args,
Methodproxy proxy) lanza lanzamiento {
// TODO STUB de método generado automático
System.out.println ("" ... ... ...
System.out.println ("¡Hable en el escenario siguiente!");
// Llamada del método de destino
Resultado del objeto = proxy.invokesuper (obj, args);
// Ejecutar el método de destino después
System.out.println ("¡Todos aplauden y estén aliento!");
resultado de retorno;
}
}
Luego prueba:
La copia del código es la siguiente:
paquete testaop.cglib;
importar testaop.saying;
import tataop.sayingImpl;
clase pública cglibproxytest {
public static void main (string [] args) {
Cglibproxy proxy = new cglibproxy ();
// Crear clases proxy generando dinámicamente subclases
Diciendo Target = (Dicho) proxy.getProxy (dayMeMpl.class);
Target.sayhello ("Xiao Ming");
Target.talking ("Xiaoli");
}
}
El resultado no es diferente del proxy dinámico JDK.
Tanto el proxy dinámico JDK como el proxy dinámico CGLIB son mejoras en tiempo de ejecución, que se mejoran implantando el código transversal en clases proxy. A diferencia de esto, SuppectJ, que puede implantar el código transversal en el período de compilación a través de un compilador especial.