Explication détaillée du mode proxy java
Avant-propos :
Dans certains cas, un client ne veut pas ou ne peut pas référencer directement un objet. Dans ce cas, il peut passer un troisième objet appelé. un "proxy" Trois pour obtenir une référence indirecte. L'objet proxy peut agir comme intermédiaire entre le client et l'objet cible, et peut supprimer le contenu et les services que le client ne peut pas voir ou ajouter des services supplémentaires dont le client a besoin via l'objet proxy.
En termes simples, le mode proxy consiste à accéder à un objet réel via un objet proxy et peut ajouter certaines fonctions à l'objet comme le mode décoration.
Procuration statique
Le proxy dit statique signifie que la classe proxy existe déjà avant l'exécution du programme, c'est-à-dire que lorsque nous écrivons le code, nous avons déjà écrit le code. de la classe proxy et du proxy dynamique La classe proxy est automatiquement générée lors de l'exécution du programme.
La description est trop abstraite. Il suffit de regarder le code et vous comprendrez ce qui se passe
main
public class Main { public static void main(String[] args) { Water water = new Water(); WaterProxy waterProxy = new WaterProxy(water); waterProxy.drink(); } }
Interface
//代理类与被代理类共同实现的接口 public interface Drink { void drink(); }
Classe proxy
//被代理的类 public class Water implements Drink { @Override public void drink() { System.out.println("drink water"); } }
Classe proxy
//代理类 //与被代理类实现同一个接口 public class DrinkProxy implements Drink { private Drink drinkImpl; //通过构造函数传入Water对象 public DrinkProxy(Drink drinkImpl) { this.drinkImpl = drinkImpl; } @Override public void drink() { //在执行被代理对象的方法前做一些事情 System.out.println("before drink"); //执行被代理对象的方法 drinkImpl.drink(); //在执行被代理对象的方法后做一些事 System.out.println("after drink"); } }
Résultat de l'exécution
before drink drink water after drink
Procuration dynamique
Parfois, nous voulons simplement changer la classe représentée par la classe proxy, mais l'objet proxy fait la même chose avant et après l'exécution de la méthode de l'objet réel. Comme le dit le proverbe, la classe proxy à toute épreuve est le proxy fluide. classe. Avec un proxy statique, vous ne pouvez proxy que des classes qui implémentent la même interface. Si vous souhaitez proxy n'importe quelle classe, vous devez écrire de nombreuses classes proxy en double. À l'heure actuelle, nous pouvons utiliser un proxy dynamique. Java a fourni un ensemble d'outils pratiques pour implémenter un proxy dynamique.
Méthodes de la classe java.lang.reflect.Proxy qui peuvent générer dynamiquement des objets proxy
/** *返回实现了指定接口的对象,调用代理对象的方法会调用 *InvocationHandler的invoke方法 * * @param loader 获取代理类所使用的类加载器 * @param interfaces 代理类所要实现的接口 * @param h 实现了InvocationHandler接口的对象 * @return 代理对象 */ public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)
Interface InvocationHandler
/** *每个代理类都有一个关联的InvocationHandler *当代理对象执行一个方法的时候会直接执行invoke方法 */ public interface InvocationHandler { /** * @param 调用该方法的代理对象 * @param method 代理对象所调用的方法 * @param args 调用的方法的参数 * @return 调用的方法的返回值 */ public Object invoke(Object proxy, Method method, Object[] args) }
La description est toujours abstraite, elle est plus facile à comprendre en regardant des exemples réels
Exemple
Classe d'implémentation de l'interface InvocationHandler
public class CommonInvocationHandler implements InvocationHandler { //被代理的对象 private Object proxied; public CommonInvocationHandler(Object proxied) { this.proxied = proxied; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //在调用被代理对象的方法前做一些事情 System.out.println("before doing something"); //调用被代理对象的方法 Object result = method.invoke(proxied, args); //在调用被代理对象的方法后做一些事情 System.out.println("after doing something");; return result; } }
Principal
public class Main { public static void main(String[] args) { //被代理的对象 Water water = new Water(); //动态获取代理对象 Drink waterProxy = (Drink) Proxy.newProxyInstance(water.getClass().getClassLoader(), water.getClass().getInterfaces(), new CommonInvocationHandler(water)); //通过代理对象调用方法 waterProxy.drink(); } }
Résultat de sortie
before doing something drink water after doing something
Vous n'avez pas besoin d'un objet proxy spécifique, mais il doit y avoir une interface correspondante (les classes qui n'implémentent pas l'interface peuvent utiliser cglib pour implémenter un proxy dynamique) avant vous pouvez obtenir dynamiquement l'objet proxy. Par exemple, Retrofit, récemment populaire, utilise un proxy dynamique pour effectuer des requêtes réseau directement via l'interface déclarée.
Exemple
Simulation simple de rénovation
Annotation POST
//Post请求注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface POST { String value() default ""; }
Annotation de requête
//Post请求注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface POST { String value() default ""; }
Interface de service
public interface Service { //用POST注解声明请求的方式和相对路径 @POST("/login") //@Query注解声明请求的参数名 void login(@Query("username")String username, @Query("password")String password); }
Principale
public class Main { public static void main(String[] args) { // 动态获取Service接口的代理 Service service = (Service) Proxy.newProxyInstance(Service.class.getClassLoader(), new Class[] { Service.class }, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 通过注解获取请求的相对路径 String retativePath = ((POST) method.getAnnotations()[0]).value(); System.out.println("relative path: " + retativePath); // 获取参数的注解 Annotation[][] parameterAnnotations = method.getParameterAnnotations(); // 通过参数的注解获取请求参数 for (int i = 0; i < parameterAnnotations.length; i++) { if (parameterAnnotations[i].length != 0) { for (int j = 0; j < parameterAnnotations[i].length; j++) { Query query = (Query) parameterAnnotations[i][j]; System.out.println(query.value() + ": " + args[i].toString()); } } } return null; } }); // 调用代理对象的方法 service.login("hello", "world"); } }
Merci d'avoir lu, j'espère que cela pourra aider tout le monde, merci pour votre soutien à ce site !
Pour des explications plus détaillées et des exemples d'articles sur le code sur le mode proxy en Java, veuillez faire attention au site Web PHP chinois !