Red de conocimiento informático - Problemas con los teléfonos móviles - Una breve discusión sobre las diferencias entre los dos proxies de Spring, JDK y CGLIB

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.