Una breve discusión sobre las diferencias entre los dos proxies de Spring, JDK y CGLIB
1. Diferencia de principio
El proxy dinámico de Java utiliza el mecanismo de reflexión para generar una clase anónima que implementa la interfaz del proxy y llama a InvokeHandler para procesarla antes de llamar al método específico.
El proxy dinámico cglib utiliza el paquete de código abierto asm para cargar el archivo de clase de la clase de objeto proxy y procesarlo modificando su código de bytes para generar una subclase.
1. Si el objeto de destino implementa la interfaz, el proxy dinámico de JDK se utilizará para implementar AOP de forma predeterminada.
2 Si el objeto de destino implementa la interfaz, se puede forzar CGLIB. que se utilizará para implementar AOP
3 Si el objeto de destino no implementa la interfaz, se debe utilizar la biblioteca CGLIB y Spring convertirá automáticamente entre el proxy dinámico JDK y CGLIB
. ¿Cómo forzar el uso de CGLIB para implementar AOP?
(1) Agregue la biblioteca CGLIB, SPRING_HOME/cglib/*.jar
(2) Agregue
¿Cuál es la diferencia entre el proxy dinámico JDK y la generación de código de bytes CGLIB?
(1) El proxy dinámico JDK solo puede generar servidores proxy para clases que implementan interfaces, pero no para clases
(2) CGLIB implementa servidores proxy para clases, principalmente para clases específicas. subclase y anula los métodos que contiene
Debido a que es herencia, es mejor no declarar la clase o método como final
2. html] ver copia simple
paquete com.fy.spring.proxy;
interfaz pública UserManager {
public void addUser(String id, String contraseña);
public void delUser(String id);
}
[html] ver copia simple
paquete com.fy.spring. proxy;
clase pública UserManagerImpl implementa UserManager {
public void addUser(ID de cadena, contraseña de cadena) {
System.out.println(".: El ¡Se utiliza el método UserManagerImpl.addUser()! ");
}
public void delUser(String id) {
System.out.println(". : ¡El método UserManagerImpl.delUser() ya no se utiliza ");
}
}
Clase de proxy dinámico JDK
[html] ver copia simple
paquete com.fy.spring.proxy;
importar java.lang.reflect.InvocationHandler
importar java.lang. reflejar .Método;
importar java.lang.reflect.Proxy
/**
*
* Clase de proxy dinámico JDK
*
*
*/
la clase pública JDKProxy implementa InvocationHandler {
objeto privado targetObject;/ /Objeto objetivo que requiere proxy
p>
objeto público newProxy(Object targetObject) {//Pase el objeto de destino para el proxy
this.targetObject = targetObject
return Proxy.newProxyInstance(targetObject.getClass; ().getClassLoader(),
targetObject.getClass().getInterfaces(), this);//Devolver objeto proxy
}
Invocación de objeto público (Proxy de objeto, método de método, argumentos de objeto []) // método de invocación
throws Throwable {
checkPopedom(); //Generalmente usamos funciones para procesamiento lógico como este lugar Simular permisos de verificación
Objeto ret = null; //Establecer el valor de retorno del método
ret = método.invoke(targetObject, args); //Llamar al método de invocación, ret); almacena el método El valor de retorno de
return ret
}
private void checkPopedom() {//Ejemplo de simulación de verificación de permisos
System. out.println(".:Comprobar permisos checkPopedom()!";
}
}
Clase de proxy dinámico CGLibProxy
[html] ver copia simple
paquete com.fy.spring.proxy
importar java.lang.reflect.Method
importar; net.sf.cglib.proxy.Enhancer;
importar net.sf.cglib.proxy.MethodInterceptor
importar net.sf.cglib.proxy.MethodProxy;
/ **
* Instancia de la clase de proxy dinámico CGLibProxy
*
*
*/
clase pública CGLibProxy implementa MethodInterceptor {
Objeto privado targetObject;//CGLib necesita el objeto de destino del proxy
Objeto público createProxyObject(Objeto obj) {
this.targetObject = obj ;
Mejorador potenciador = nuevo Mejorador();
enhancer.setSuperclass(obj.getClass());
enhancer.setCallback (esto);
p>
Objeto proxyObj = potenciador.create();
/p>
devolver proxyObj;//Devolver objeto proxy
}
interceptación de objeto público (proxy de objeto, método de método, argumentos de objeto[],
MethodProxy métodoProxy) throwable {
Objeto obj = null
if ("addUser".equals(method.getName())) {//Método de filtro
checkPopedom();//Verificar permisos
}
obj = método.invoke(targetObject, args);
return obj; >
}
private void checkPopedom() {
System.out.println(".:Verificar permisos checkPopedom()!"
}
}
Clase de prueba:
[html] ver copia simple
cliente de clase pública {
public static void main(String[] args) {
UserManager userManager = (UserManager) new CGLibProxy()
.createProxyObject(new UserManagerImpl()
System.out.println("-----------CGLibProxy-------------");
userManager.addUser("tom" , "raíz");
System.out.println("-----------JDKProxy-------------"); p> p>
JDKProxy jdkPrpxy = nuevo JDKProxy();
UserManager userManagerJDK = (UserManager) jdkPrpxy
.newProxy(nuevo UserManagerImpl()); p> userManagerJDK.addUser("tom", "root");
}
}
Resultados de la ejecución:
[html ] ver copia simple
----------CGLibProxy-------------
¡Comprobar permisos checkPopedom()! /p >
¡Usé el método UserManagerImpl.addUser()!
-----------JDKProxy-------------
Comprobar permisos checkPopedom()
¡Usé el método UserManagerImpl.addUser()!
3. Diferencias
El proxy JDK no necesita depender de bibliotecas de terceros. Siempre que se requiera el entorno JDK, se puede utilizar como proxy. requisitos.
Solicitud
* Implementar InvocationHandler
* Usar Proxy.newProxyInstance para generar objetos proxy
* El objeto proxy debe implementar la interfaz
Usar Proxy dinámico JDK, una interfaz que la clase de destino debe implementar. Si una clase no implementa la interfaz, no se puede generar el objeto proxy.
CGLib debe depender de la biblioteca de clases CGLib. El principio de Cglib es generar una subclase para la clase de destino y cubrir todos los métodos que contiene, por lo que la clase de destino y los métodos no pueden declararse como tipos finales. Para entornos de programación de interfaces, se recomienda utilizar el agente JDK. Desde la perspectiva de la eficiencia de ejecución, la eficiencia del proxy dinámico de Cglib es mayor. La implementación del interceptor en Hibernate tiene en cuenta las condiciones que no requieren otras interfaces. Los agentes relevantes en Hibernate se ejecutan utilizando CGLib.