Proxy dynamique JAVA
mode proxy
Le modèle d'agent est un modèle de conception Java couramment utilisé. Sa caractéristique est que la classe d'agent et la classe de délégué ont la même interface. La classe d'agent est principalement responsable du prétraitement des messages pour la classe de délégué, du filtrage des messages et de la transmission des messages à la classe de délégué. , et traiter les messages par la suite. Il existe généralement une association entre une classe proxy et une classe déléguée. Un objet d'une classe proxy est associé à un objet d'une classe déléguée. L'objet de la classe proxy lui-même n'implémente pas réellement le service, mais en appelant les méthodes appropriées. de l’objet de la classe déléguée. Fournir des services spécifiques.
Selon la période de création de l'agent, la classe d'agent peut être divisée en deux types.
Proxy statique : Créé par des programmeurs ou généré automatiquement par un outil spécifique puis compilé. Avant l'exécution du programme, le fichier .class de la classe proxy existe déjà.
Proxy dynamique : créé dynamiquement à l'aide du mécanisme de réflexion lorsque le programme est en cours d'exécution.
Jetez d’abord un œil au proxy statique :
1.Count.java
Copiez le code comme suit :
paquet net.battier.dao;
/**
* Définir une interface de compte
*
* @auteur Administrateur
*
*/
interface publique Nombre {
// Afficher la méthode du compte
public void queryCount();
//Modifier la méthode du compte
public void updateCount();
}
2. CountImpl.java
Copiez le code comme suit :
paquet net.battier.dao.impl;
importer net.battier.dao.Count ;
/**
* Classe de délégué (y compris la logique métier)
*
* @auteur Administrateur
*
*/
la classe publique CountImpl implémente Count {
@Outrepasser
public void queryCount() {
System.out.println("Afficher la méthode du compte...");
}
@Outrepasser
public void updateCount() {
System.out.println("Modifier la méthode du compte...");
}
}
CountProxy.java
paquet net.battier.dao.impl;
importer net.battier.dao.Count ;
/**
* Il s'agit d'une classe proxy (classe d'implémentation CountImpl améliorée)
*
* @auteur Administrateur
*
*/
la classe publique CountProxy implémente Count {
privé CountImpl countImpl;
/**
* Remplacer le constructeur par défaut
*
* @param countImpl
*/
public CountProxy (CountImpl countImpl) {
this.countImpl = countImpl;
}
@Outrepasser
public void queryCount() {
System.out.println("Avant le traitement de la transaction");
// Appelez la méthode de la classe déléguée ;
countImpl.queryCount();
System.out.println("Après le traitement de la transaction");
}
@Outrepasser
public void updateCount() {
System.out.println("Avant le traitement de la transaction");
// Appelez la méthode de la classe déléguée ;
countImpl.updateCount();
System.out.println("Après le traitement de la transaction");
}
}
3. TestCount.java
Copiez le code comme suit :
paquet net.battier.test;
importer net.battier.dao.impl.CountImpl;
importer net.battier.dao.impl.CountProxy ;
/**
*Classe de comptage de tests
*
* @auteur Administrateur
*
*/
classe publique TestCount {
public static void main (String[] arguments) {
CountImpl countImpl = new CountImpl();
CountProxy countProxy = new CountProxy(countImpl);
countProxy.updateCount();
countProxy.queryCount();
}
}
En observant le code, vous constaterez que chaque classe proxy ne peut servir qu'une seule interface. De cette façon, trop de proxys seront inévitablement générés lors du développement du programme. De plus, toutes les opérations de proxy sont les mêmes, à l'exception de la méthode qu'elles appellent. doit être répété à ce moment. La meilleure façon de résoudre ce problème est d'utiliser une classe proxy pour compléter toutes les fonctions proxy. Dans ce cas, un proxy dynamique doit être utilisé pour le compléter.
Jetons un coup d'œil au proxy dynamique :
Le proxy dynamique JDK contient une classe et une interface :
Interface du gestionnaire d'appel :
interface publique InvocationHandler {
public Object Invoke (Object Proxy, Method Method, Object[] args) lance Throwable ;
}
Description du paramètre :
Proxy d'objet : fait référence à l'objet proxy.
Méthode méthode : la méthode à appeler
Object[] args : paramètres requis lors de l'appel de la méthode
Vous pouvez considérer une sous-classe de l'interface InvocationHandler comme la classe d'opération finale d'un proxy, remplaçant ProxySubject.
Classe proxy :
La classe Proxy est une classe spécialisée dans les opérations de proxy. Cette classe peut être utilisée pour générer dynamiquement des classes d'implémentation pour une ou plusieurs interfaces. Cette classe fournit les méthodes d'opération suivantes :
Objet statique public newProxyInstance (chargeur ClassLoader, interfaces Class<?>[],
Gestionnaire d'appels h)
lance IllegalArgumentException
Description du paramètre :
Chargeur ClassLoader : chargeur de classe
Interfaces de classe<?>[] : obtenir toutes les interfaces
InvocationHandler h : récupère l'instance de sous-classe de l'interface InvocationHandler
Ps : chargeur de classe
Une instance de la classe ClassLoader est requise dans la méthode newProxyInstance() dans la classe Proxy. ClassLoader correspond en fait au chargeur de classe. Il existe trois chargeurs de classe principaux en Java ;
Booststrap ClassLoader : ce chargeur est écrit en C++ et n'est pas visible dans le développement général ;
Extension ClassLoader : utilisé pour charger des classes d'extension, correspondant généralement aux classes du répertoire jre/lib/ext ;
AppClassLoader : (par défaut) charge la classe spécifiée par classpath, qui est le chargeur le plus couramment utilisé.
proxy dynamique
Contrairement à la classe proxy statique, il existe la classe proxy dynamique. Le bytecode de la classe proxy dynamique est généré dynamiquement par le mécanisme de réflexion Java lorsque le programme est en cours d'exécution, sans que les programmeurs aient besoin d'écrire manuellement son code source. Les classes proxy dynamiques simplifient non seulement le travail de programmation, mais améliorent également l'évolutivité des systèmes logiciels, car le mécanisme de réflexion Java peut générer tout type de classe proxy dynamique. La classe Proxy et l'interface InvocationHandler du package java.lang.reflect offrent la possibilité de générer des classes proxy dynamiques.
Exemple de proxy dynamique :
1.BookFacade.java
Copiez le code comme suit :
paquet net.battier.dao;
interface publique BookFacade {
public void addBook();
}
2.BookFacadeImpl.java
Copiez le code comme suit :
paquet net.battier.dao.impl;
importer net.battier.dao.BookFacade ;
classe publique BookFacadeImpl implémente BookFacade {
@Outrepasser
public void addBook() {
System.out.println("Ajouter une méthode de livre...");
}
}
BookFacadeProxy.java
paquet net.battier.proxy;
importer java.lang.reflect.InvocationHandler ;
importer java.lang.reflect.Method ;
importer java.lang.reflect.Proxy ;
/**
* Classe proxy proxy dynamique JDK
*
* @auteur étudiant
*
*/
classe publique BookFacadeProxy implémente InvocationHandler {
Cible d'objet privé ;
/**
* Liez l'objet délégué et renvoyez une classe proxy
* @param cible
* @retour
*/
liaison d'objet public (cible de l'objet) {
this.target = cible ;
//Obtenir l'objet proxy
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this); //Pour lier l'interface (c'est un défaut, cglib compense ce défaut)
}
@Outrepasser
/**
* Méthode d'appel
*/
appel d'objet public (proxy d'objet, méthode de méthode, arguments Object[])
lance Jetable {
Résultat de l'objet = null ;
System.out.println("Les choses commencent");
//méthode d'exécution
result=method.invoke(target, args);
System.out.println("Fin des choses");
renvoyer le résultat ;
}
}
3. TestProxy.java
Copiez le code comme suit :
paquet net.battier.test;
importer net.battier.dao.BookFacade ;
importer net.battier.dao.impl.BookFacadeImpl;
importer net.battier.proxy.BookFacadeProxy ;
classe publique TestProxy {
public static void main (String[] arguments) {
Proxy BookFacadeProxy = new BookFacadeProxy();
BookFacade bookProxy = (BookFacade) proxy.bind(new BookFacadeImpl());
bookProxy.addBook();
}
}
Cependant, le proxy dynamique du JDK repose sur l'implémentation de l'interface. Si certaines classes n'implémentent pas l'interface, le proxy JDK ne peut pas être utilisé, le proxy dynamique cglib doit donc être utilisé.
Proxy dynamique Cglib
Le mécanisme de proxy dynamique du JDK ne peut que proxy les classes qui implémentent des interfaces. Les classes qui ne peuvent pas implémenter d'interfaces ne peuvent pas implémenter le proxy dynamique du JDK. Son principe est de générer une sous-classe pour la classe cible spécifiée et de remplacer les méthodes pour obtenir une amélioration. , mais comme l'héritage est utilisé, la classe finale modifiée ne peut pas être proxy.
Exemple
1.BookFacadeCglib.java
Copiez le code comme suit :
paquet net.battier.dao;
interface publique BookFacade {
public void addBook();
}
2.BookCadeImpl1.java
Copiez le code comme suit :
paquet net.battier.dao.impl;
/**
* Il s'agit d'une classe d'implémentation qui n'implémente pas l'interface
*
* @auteur étudiant
*
*/
classe publique BookFacadeImpl1 {
public void addBook() {
System.out.println("Méthode courante pour ajouter des livres...");
}
}
3.BookFacadeProxy.java
Copiez le code comme suit :
paquet net.battier.proxy;
importer java.lang.reflect.Method ;
importer net.sf.cglib.proxy.Enhancer ;
importer net.sf.cglib.proxy.MethodInterceptor ;
importer net.sf.cglib.proxy.MethodProxy ;
/**
* Utiliser le proxy dynamique cglib
*
* @auteur étudiant
*
*/
classe publique BookFacadeCglib implémente MethodInterceptor {
Cible d'objet privé ;
/**
* Créer un objet proxy
*
* @param cible
* @retour
*/
objet public getInstance (cible de l'objet) {
this.target = cible ;
Enhancer Enhancer = new Enhancer();
Enhancer.setSuperclass(this.target.getClass());
// méthode de rappel
Enhancer.setCallback(this);
//Créer un objet proxy
return Enhancer.create();
}
@Outrepasser
// méthode de rappel
interception d'objet public (objet obj, méthode méthode, arguments objet [],
MethodProxy proxy) lance Throwable {
System.out.println("Les choses commencent");
proxy.invokeSuper(obj, args);
System.out.println("Fin des choses");
renvoie null ;
}
}
4. TestCglib.java
Copiez le code comme suit :
paquet net.battier.test;
importer net.battier.dao.impl.BookFacadeImpl1 ;
importer net.battier.proxy.BookFacadeCglib;
classe publique TestCglib {
public static void main (String[] arguments) {
BookFacadeCglib cglib=new BookFacadeCglib();
BookFacadeImpl1 bookCglib=(BookFacadeImpl1)cglib.getInstance(new BookFacadeImpl1());
bookCglib.addBook();
}
}