El proxy dinàmic es divideix en servidor intermediari dinàmic JDK i proxy dinàmic cglib.El ús comú està en el AOP de Spring.
- proxy dinàmic JDK: el mètode amb el mateix nom en la interfície s’usa per trucar a mètode de la mateixa implementació en la classe de proxy generada dinàmicament; el proxy implementa la classe d’interfície i la classe sense la interfície no pot fer servir el proxy dinàmic JDK. Zh
- Proxy dinàmic de Cglib: a l’heretar la classe de negocis, la classe de proxy dinàmic generada és una subclasse de la classe de negocis, que se substitueix a l’anul·lar el mètode de negocis; la classe modificada final no es pot intermediari. Per utilitzar l’agent cglib, ha d’importar el paquet jar cglib.
Proxy dinàmic JDK
La classe de proxy utilitzada pel proxy dinàmic jdk és realment creada per la JVM quan el programa crida a l’objecte de la classe intermediari. El motor s’executa i després realitza trucades a mètodes a través d’aquest objecte de classe intermediari.
Per què el servidor intermediari dinàmic JDK implementa interfícies?
Quan el proxy dinàmic jdk s’implementa utilitzant InvocationHandler, la classe proxy ha d’heretar proxy. Si bé la classe proxy ha heretar per obtenir els mètodes rellevants i els constructors InvocationHandler, java no pot heretar ambdues classes a el mateix temps. Per establir una connexió amb la classe proxy, només el Una interfície
Implementació de l’intermediari dinàmic JDK (la interfície té classe d’implementació)
1. Crear classes i interfícies intermediari
public interface BuyService { void buy(String name);}
import com.uv.service.BuyService;public class BuyServiceImpl implements BuyService{ @Override public void buy(String name) { System.out.println("buy " + name); }}
Creeu una classe de proxy InvokeProxy i implementi la interfície InvocationHandler
/* * @author uv * @date 2018/10/12 13:04 * */import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class InvokeProxy implements InvocationHandler{ // El objeto real para proxy private Object subject; public InvokeProxy(Object subject) { this.subject = subject; } /** * El objeto real que el proxy @param está representando * Método @param Objeto Método para llamar a un método del objeto real * @param args Los parámetros aceptados al llamar a un método del objeto real */ @Override public Object invoke(Object proxy, Method method, Object args) throws Throwable { System.out.println("start method:" + method.getName()); method.invoke(subject, args); System.out.println("end method:" + method.getName()); return null; }}
3. Ús de proxy dinàmic
import com.uv.proxy.InvokeProxy;import com.uv.service.BuyService;import com.uv.service.impl.BuyServiceImpl;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;/** * <uv> */public class Main { public static void main(String args) { // El objeto real para proxy BuyService service = new BuyServiceImpl(); InvocationHandler handler = new InvokeProxy(service); /* * El nuevo método ProxyInstance del proxy para crear nuestro objeto proxy * El primer parámetro handler.getClass (). GetClassLoader () usa el objeto ClassLoader de la clase handler para cargar nuestro objeto proxy * El segundo parámetro realSubject.getClass (). GetInterfaces (), la interfaz proporcionada para el objeto proxy es la interfaz implementada por el objeto real, lo que significa que quiero proxy del objeto real, por lo que puedo llamar a los métodos en este conjunto de interfaces Arriba * El tercer controlador de parámetros, asocia este objeto proxy con el objeto InvocationHandler anterior */ BuyService buyService = (BuyService)Proxy.newProxyInstance(handler.getClass().getClassLoader(), service.getClass().getInterfaces(), handler); buyService.buy("cap"); }}
Implementació de l’intermediari dinàmic JDK (la interfície no té classe d’implementació)
1. Crear una interfície intermediari
public interface SellService { String sell(String name);}
2. Creu la classe de proxy InvokeProxy i implementi la interfície InvocationHandler
/* * @author uv * @date 2018/10/12 13:56 * No hay proxy dinámico que implemente la interfaz de clase */import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class InterfaceProxy implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object args) throws Throwable { System.out.println ("Llamada al método de interfaz iniciada"); // método de ejecución System.out.println("method name:" + method.getName()); System.out.println("method args:" + args); System.out.println ("Fin de la llamada al método de interfaz"); return "sell " + args; } public static <T> T newInterfaceProxy(Class<T> intf) { ClassLoader classLoader = intf.getClassLoader(); Class<?> interfaces = new Class{intf}; InterfaceProxy proxy = new InterfaceProxy(); return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy); }}
3. Ús de proxy dinàmic
import com.uv.proxy.InterfaceProxy;import com.uv.service.SellService;/** * <uv> */public class Main { public static void main(String args) { SellService sellService = InterfaceProxy.newInterfaceProxy(SellService.class); System.out.println(sellService.sell("cap")); }}
Proxy dinàmic Cglib
Cglib implementa proxies per a les classes. El principi és generar una subclasse de la classe de negocis especificada i anul·lar els mètodes de negocis per implementar el servidor intermediari. A causa de que s’usa l’herència, no pot proxy classes modificades finals. Zh
1. Afegir dependències
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.4</version> </dependency>
2. Creeu una classe proxy sense implementar una interfície (també és possible implementar una interfície, no afecta)
/* * @author uv * @date 2018/10/12 14:37 * Clase de proxy que no implementa ninguna interfaz */public class SayService { public void say(String name) { System.out.println("Hello " + name); }}
3. Implementi la interfície proxy de l’mètode MethodInterceptor i creï una classe proxy
/* * @author uv * @date 2018/10/12 14:36 * */import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class CglibProxy implements MethodInterceptor{ // Objeto comercial, que se representará private Object subject; // Equivalente al enlace en proxy dinámico JDK public <T> T getInstance(T subject) { // Asigna valores a objetos comerciales this.subject = subject; // Crear potenciador, usado para crear clases de proxy dinámico Enhancer enhancer = new Enhancer(); // Especifique la clase de negocio a proxy para el potenciador (es decir, especifique la clase padre para la clase de proxy generada a continuación) enhancer.setSuperclass(this.subject.getClass()); // Establezca la devolución de llamada: se llamará a CallBack para todos los métodos en la clase proxy, y Callback debe implementar el método intercept () para bloquear enhancer.setCallback(this); // Crea un objeto de clase proxy dinámico y devuelve return (T)enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object args, MethodProxy proxy) throws Throwable { System.out.println("before"); // Llamar al método de la clase de negocios (en la clase padre) proxy.invokeSuper(obj, args); System.out.println("after"); return null; }}
4. Ús de proxy dinàmic
import com.uv.proxy.CglibProxy;import com.uv.service.impl.SayService;/** * <uv> */public class Main { public static void main(String args) { // El objeto que se representa SayService sayService = new SayService(); // clase de proxy CglibProxy cglibProxy = new CglibProxy(); SayService service = cglibProxy.getInstance(sayService); service.say("Tom"); }}