Modo proxy de Java JDKProxy y CGLibProxy

Modo proxy de Java

modo proxy

Proxy (Proxy) es un patrón de diseño que proporciona otra forma de acceder al objeto de destino, es decir, acceder al objeto de destino a través del objeto proxy. La ventaja de esto es que se pueden mejorar las operaciones funcionales adicionales sobre la base del objeto de destino implementación, es decir Extender la función del objeto de destino.
Aquí se usa una idea en programación: no modifique el código o el método que otros han escrito a voluntad. Si necesita modificarlo, puede extender el método por proxy

Permítanme dar un ejemplo para ilustrar el papel de un agente: supongamos que queremos invitar a una estrella, por lo que en lugar de conectarnos directamente con la estrella, debemos contactar al agente de la estrella para lograr el mismo propósito. La estrella es un objeto objetivo, y solo necesita ser responsable de las actividades que se muestran, y otros asuntos triviales se dejan a su agente (corredor) para que los resuelva. Este es un ejemplo de pensamiento de agencia en la realidad.

Los puntos clave del modo proxy son: el objeto proxy y el objeto de destino. El objeto proxy es una extensión del objeto de destino y llamará al objeto de destino.

Modo jdkProxy (proxy dinámico)

El modo jdkProxy (proxy dinámico) tiene las siguientes características:

  1. Objeto proxy, no es necesario implementar la interfaz
  2. La generación de objetos proxy es usar la API de JDK para construir dinámicamente objetos proxy en la memoria (necesitamos especificar el tipo de interfaz implementada mediante la creación de objetos proxy/objetos de destino)
  3. El proxy dinámico también se denomina: proxy JDK, proxy de interfaz

JDK solo necesita usar el método newProxyInstance para implementar el proxy, pero este método necesita recibir tres parámetros. El método de escritura completo es:

static Object newProxyInstance(ClassLoader loader, Class<?>[] 
		interfaces,InvocationHandler h )

Tenga en cuenta que este método es un método estático en la clase Proxy, y los tres parámetros recibidos son:

  • Cargador ClassLoader: especifique el objeto de destino actual para usar el cargador de clases, el método para obtener el cargador es fijo
  • Class<?>[] interfaces: el tipo de la interfaz implementada por el objeto de destino, usando el método genérico para confirmar el tipo
  • InvocationHandler h : procesamiento de eventos, cuando se ejecuta el método del objeto de destino, se activará el método del controlador de eventos y el método del objeto de destino que se está ejecutando actualmente se pasará como un parámetro

Ejemplo de código:
clase de interfaz: ISomeClass.java

//接口
public interface ISomeClass {
    
    
	void doSomething(String mess);
	String doSomething(int num);
}

La clase de objeto de destino, es decir, la clase de implementación de la interfaz:
SomeClass.java

public class SomeClass implements ISomeClass {
    
    

	public SomeClass() {
    
    
	}
	
	@Override
	public void doSomething(String mess) {
    
    
		System.out.println(mess);
	}

	@Override
	public String doSomething(int num) {
    
    
		return "num : " + String.valueOf(num);
	}
	
	public void doSomething() {
    
    
		System.out.println("This is doSomething() method.");
	}
}

Clase de fábrica de proxy:
JDKProxy.java

public class JDKProxy {
    
    
	
	public JDKProxy() {
    
    
	}

	@SuppressWarnings("unchecked")
	public static <T> T getProxy(Object object) {
    
    
		Class<?> klass = object.getClass();
		ClassLoader loader = klass.getClassLoader(); 	// 类加载器
		Class<?>[] interfaces = klass.getInterfaces();	//获得这个对象所实现的所有接口
		
		return (T) Proxy.newProxyInstance(loader, interfaces, 
				new InvocationHandler() {
    
    
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    

						System.out.println("在执行方法之前,可以做些事……");
						Object result = method.invoke(object, args);
						System.out.println("在执行方法之后前,也可以做些事……");
						return result;
					}
				});
	}
	
}

Clase de prueba:

public class Test {
    
    
	public static void main(String[] args) {
    
    
		SomeClass some = new SomeClass();
		//将ISomeClass的实现类,装入代理工厂
		ISomeClass someProxy = (ISomeClass) JDKProxy.getProxy(some);
		someProxy.doSomething("这是第一条消息");
	}
}

Resultados de la prueba:inserte la descripción de la imagen aquí

Modo CGLibProxy

El modo de proxy dinámico requiere que el objeto de destino sea un objeto de destino que implemente una interfaz, pero a veces el objeto de destino es solo un objeto único que no implementa ninguna interfaz. En este momento, el proxy se puede implementar subclasificando el objeto de destino. Este método se llama: CGLib Proxy

El proxy Cglib, también llamado proxy de subclase, crea un objeto de subclase en la memoria para ampliar la función del objeto de destino.

  • El proxy dinámico de JDK tiene una limitación, es decir, los objetos que usan el proxy dinámico deben implementar una o más interfaces. Si desea representar una clase que no implementa una interfaz, puede usar Cglib para implementarla.
  • Cglib es un poderoso paquete de generación de código de alto rendimiento que puede extender las clases de Java e implementar interfaces de Java en tiempo de ejecución. Es ampliamente utilizado por muchos marcos AOP, como Spring AOP y synaop, para proporcionarles interceptación de métodos (intercepción).
  • La capa inferior del paquete Cglib es convertir el código de bytes y generar nuevas clases mediante el uso de un marco de procesamiento de código de bytes pequeño y de bloque ASM. Se desaconseja el uso directo de ASM porque requiere que tenga la estructura interna de JVM, incluido el formato del archivo de clase. y El conjunto de instrucciones es muy familiar.

Método de implementación del proxy de la subclase Cglib:

  1. El archivo jar de cglib debe importarse, pero el paquete principal de Spring ya incluye la función Cglib, por lo que se pring-core-3.2.5.jarpuede importar directamente.
  2. Después de que se introduce el paquete de funciones, las subclases se pueden construir dinámicamente en la memoria
  3. La clase de proxy no puede ser final, de lo contrario se informará un error
  4. Si el método del objeto de destino es final/estático, no se interceptará, es decir, no se ejecutará ningún método comercial adicional del objeto de destino.

La clase de objeto de destino anterior es la clase de implementación de la interfaz: aunque SomeClass.java implementa la interfaz ISomeclass, también tiene sus propios métodos.

public void doSomething() {
    
    
		System.out.println("This is doSomething() method.");
	}

Entonces podemos usar el proxy Cglib para implementar el
ejemplo de código del método anterior:

 	//给目标对象创建一个代理对象
	@SuppressWarnings("unchecked")
	public static <T> T getProxy(Object object) {
    
    
		Class<?> klass = object.getClass();
		//1.工具类
		Enhancer enhancer = new Enhancer();
		//2.设置父类
		enhancer.setSuperclass(klass);
		//3.设置回调函数
		enhancer.setCallback(new MethodInterceptor() {
    
    
			@Override
			public Object intercept(Object obj, Method method, 
					Object[] args, MethodProxy mObj) throws Throwable {
    
    
				System.out.println("前置拦截");
				//执行目标对象的方法
				Object result = method.invoke(object, args);
				System.out.println("后置拦截");
				
				return result;
			}
		});
		//4.创建子类(代理对象)
		return (T) enhancer.create();
	}

Clase de prueba:

	public static void main(String[] args) {
    
    
		//创建目标对象
		SomeClass some = new SomeClass();
		//将目标对象装入Cglib代理
		SomeClass somePro = CGLibProxy.getProxy(some);
		//用Cglib执行非接口类方法
		somePro.doSomething();
	}

Resultado de la ejecución:
inserte la descripción de la imagen aquífrente a estos dos modos de proxy
, si el objeto de destino agregado al contenedor tiene una interfaz de implementación, use el proxy JDK;
si el objeto de destino no implementa la interfaz, use el proxy Cglib

Supongo que te gusta

Origin blog.csdn.net/adaizzz/article/details/109545863
Recomendado
Clasificación