1. Mode d'agent
Le modèle proxy est appelé proxy ou substitut en anglais, et les deux peuvent être traduits par «agent» en chinois. Le soi-disant proxy signifie qu'une personne ou une institution prend des mesures au nom d'une autre personne ou d'une autre institution. Dans certains cas, un client ne veut pas ou ne peut pas se référer directement à un objet, et l'objet proxy peut agir comme un intermédiaire entre le client et l'objet cible.
Expliquez les différences entre divers agents en simulant simplement le processus d'exécution des transactions
1.1 Proxy statique
Le code source est créé par les programmeurs ou généré automatiquement par des outils spécifiques puis compilé. Avant que le programme ne s'exécute, le fichier .class de la classe proxy existe déjà.
Interface publique Persondao {void SavePerson ();} classe publique PersondaOIMPl implémente Persondao {@Override public void SavePerson () {System.out.println ("Save Person"); }} Transaction de classe publique {void BeginTransaction () {System.out.println ("Begin Transaction"); } void commit () {System.out.println ("commit"); }}Ensuite, écrivez une classe de proxy statique --- Implémentez l'interface Persondao
/ ** * Classe proxy statique * @author qjc * / classe publique Persondaoproxy implémente Persondao {Persondao Persondao; Transaction de transaction; Public PersondaOproxy (Persondao Persondao, Transaction Transaction) {this.persondao = Persondao; this.transaction = transaction; } @Override public void SavePerson () {this.transaction.begintransaction (); this.persondao.saveperson (); this.transaction.commit (); }}test
/ ** * Test Static Proxy * @Author qjc * / public class TestPersonProxy {@Test public void testsave () {Persondao Persondao = new PersondaOIMPl (); Transaction transaction = nouvelle transaction (); PersondAoproxy proxy = new Persondaoproxy (Persondao, transaction); proxy.saveperson (); }}Résumer:
1. Le mode proxy statique ne réutilise pas les transactions
2. Supposons qu'il y ait 100 classes et 100 proxy. Combien de méthodes y a-t-il dans l'interface, combien de méthodes doivent être implémentées dans la couche proxy et combien de transactions doivent être ouvertes et soumises autant de méthodes.
3. Si un proxy implémente plusieurs interfaces, si l'une des interfaces change (une méthode est ajoutée), le proxy doit également changer en conséquence.
1.2 JDK Dynamic Proxy
Classe de proxy dynamique: il est créé dynamiquement à l'aide d'un mécanisme de réflexion lorsque le programme est en cours d'exécution.
Le proxy dynamique de JDK doit remplir quatre conditions: 1. Interface cible 2. Classe cible 3. Intercepteur 4. Classe de procuration
En utilisant l'interface Persondao, la classe Persondaoimpl et la classe de transaction dans l'exemple précédent
Écrivez un intercepteur
Importer java.lang.reflect.invocationhandler; import java.lang.reflect.method; / ** * interceptor * 1. Importer la classe cible dans * 2. Importer des choses dans * 3. Invoquez l'achèvement: démarrer les transactions, l'appel intercepteur de la méthode d'invocation invocation et la transaction * * @Author QJC * / Classe publique Interceptor implémente Invocation Gandler {Target privé; // la transaction privée de classe cible; Public Interceptor (Object Target, Transaction Transaction) {this.target = cible; this.transaction = transaction; } / ** * @param instance proxy de la classe proxy de l'objet cible * @param méthode correspondant à l'instance de méthode qui appelle la méthode d'interface sur l'instance proxy * @param args le tableau d'objet transmis dans les valeurs de paramètre de la méthode sur l'instance proxy * @return la valeur de retour de la méthode, aucune valeur de retour n'est nul * @throws lance-throws * lance-throws {String MethodName = Method.getName (); if ("SavePerson" .Equals (MethodName) || "Deleteperson" .Equals (méthodyname) || "UpdateSerson" .Equals (méthodyname)) {this.transaction.begintransaction (); // Activer la méthode de transaction.invoke (cible); // Appelez la méthode cible this.transaction.Commit (); // Soumettre la transaction} else {méthode.invoke (cible); } return null; }}test
/ ** * Test JDK Dynamic Proxy * @Author QJC * / public class TestJdkProxy {@Test public void testsave () {/ ** * 1. Créer un objet cible * 2. Créer une transaction * 3. Créer un intercepteur * 4. Générer dynamiquement un objet proxy * / objet Target = new Persondaoil (); Transaction transaction = nouvelle transaction (); Interceptor interceptor = new interceptor (cible, transaction); / ** * Paramètre 1: Définissez le chargeur de classe utilisé par le code, qui utilise généralement le même chargeur de classe que la classe cible * Paramètre 2: Définissez l'interface implémentée par la classe proxy et utilisez la même interface que la classe cible * Paramètre 3: Définissez l'objet de rappel. Lorsque la méthode de l'objet proxy est appelée, la méthode invoquée de l'objet spécifié sera appelée * / persondao persondao = (persondao) proxy.newproxyinstance (target.getClass (). GetClassLoader (), cible.getClass (). GetInterfaces (), interceptor); Persondao.Saveperson (); }}Résumez :
1. Étant donné que la classe proxy générée par JDKProxy implémente l'interface, toutes les méthodes de la classe cible sont incluses dans la classe de proxy.
2. Toutes les méthodes de la classe proxy générée interceptent toutes les méthodes de la classe cible. Le contenu de la méthode invoquée dans l'intercepteur est exactement la composition de chaque méthode de la classe proxy.
3. Les interfaces doivent exister lors de l'utilisation de JDKProxy.
4. Les trois paramètres de la méthode Invoke peuvent accéder à l'API de la méthode appelée, les paramètres de la méthode appelée et le type de retour de la méthode appelée de la classe cible.
défaut:
1. Dans l'intercepteur, à l'exception de l'appel de la méthode cible de l'objet cible, la fonction est relativement simple. Dans cet exemple, seules les transactions peuvent être traitées.
2. L'énoncé du jugement if de la méthode invoquée dans l'intercepteur n'est pas fiable dans un environnement de développement réel, car une fois qu'il y en a beaucoup de déclarations, elle doit être écrite.
1.3 Proxy dynamique CGLIB
Utilisez la classe et la classe de transaction PersondaOimpl dans l'exemple précédent (pas d'interface)
Écrivez des cours d'interceptor
Importer net.sf.cglib.proxy.enhancer; import net.sf.cglib.proxy.methodinterceptor; import net.sf.cglib.proxy.methodproxy; / ** * CGLIB proxy interceptor * @author qjc * / public interceptor implémente la méthode d'intercepteur {l'objectif d'objet privé; // transaction de transaction privée de classe cible proxy; Public Interceptor (Object Target, Transaction Transaction) {this.target = cible; this.transaction = transaction; } / ** * Créez l'objet proxy de l'objet cible * * @return * / objet public createProxy () {// Code Enhancement Enhancer Enhancer = new Enhancer (); // Cette classe est utilisée pour générer le proxy Object Enhancer.SetCallback (this); // Le paramètre est l'interceptor Enhancer.SetSuperclass (Target.getClass ()); // Définissez la classe parent return Enhancer.create (); // Créer un objet proxy} / ** * @param obj instance de l'objet cible classe proxy classe * @param l'instance de méthode de la méthode qui appelle la méthode de la classe parent sur l'instance proxy * @param args un tableau d'objets transmis dans la méthode des valeurs de paramètre sur l'instance proxy * @Throws Methodproxy Utilisez-le pour appeler la méthode de la méthode parent * @return * @throws throws * throws * @] throws * throwsing * args, methodproxy methodproxy) lève throwsable {this.transaction.begintransaction (); méthode.invoke (cible); this.transaction.commit (); retourner null; }}test
/ ** * Test CGLIB Dynamic Proxy * L'objet proxy généré via CGLIB, la classe Proxy est une sous-classe de la classe cible * @author qjc * / classe publique TestCgliBproxy {@Test public void testSave () {Object Target = new PersondaoIMPl (); Transaction transaction = nouvelle transaction (); Interceptor interceptor = new interceptor (cible, transaction); Persondaoimpl Persondaoimpl = (persondaoimpl) interceptor.createproxy (); persondaoimpl.saveperson (); }}Résumer:
1. CGLIB est une bibliothèque de classe de génération de code puissante, haute performance et de haute qualité. Il peut étendre les classes Java et implémenter les interfaces Java pendant l'exécution.
2. Utilisez CGLIB pour générer une classe proxy comme sous-classe de la classe cible.
3. Aucune interface n'est requise pour générer des classes de proxy à l'aide de CGLIB
4. La classe proxy générée par CGLIB remplace les méthodes de la classe parent.
5. Le contenu de la méthode d'interception dans l'intercepteur est exactement la différence entre la méthode CGLIB et le proxy dynamique JDK dans la classe de proxy:
JDK:
La classe cible et la classe de proxy implémentent une interface commune
L'intercepteur doit implémenter l'interface InvocationHandler, et le contenu du corps de la méthode invoquée dans cette interface est le contenu du corps de la méthode d'objet proxy.
CGLIB:
La classe cible est la classe parent de la classe proxy
L'intercepteur doit implémenter l'interface MethodInterceptor, et la méthode d'interception dans l'interface est le corps de la méthode de la classe proxy, et le mécanisme d'amélioration du bytecode est utilisé pour créer l'objet proxy.
2. Programmation orientée
OOP (programmation orientée objet): encapsulation, héritage, polymorphisme, abstraction
Encapsulation, gestion de base et modulaire du code. Chaque classe peut avoir ses propres fonctions. Si quelque chose ne va pas, cherchez simplement quelqu'un pour discuter de la question. Du point de vue de la modification, il peut être risqué de modifier directement le code. Ce n'est pas une solution à long terme. La chose la plus naturelle est de changer de l'encapsulation de type. Cependant, comment intégrer de nouveaux types et anciens systèmes, il est donc nécessaire d'établir une relation de sang entre les classes. C'est alors l'exigence de l'héritage. Grâce à l'héritage, vous pouvez constater que ces classes sont liées et qu'il existe une relation père-fils entre eux. Ensuite, sur la base de l'héritage, les polymorphismes ont des caractéristiques décisives. Par conséquent, on pense généralement que la caractéristique la plus centrale de l'objet est en fait le polymorphisme. Les premiers sont tous jetés les bases. Le polymorphisme est sa caractéristique centrale. La méthode de réécriture dans la sous-classe représente l'extension de ce niveau, et elle peut être intégrée dans l'ancien système et peut fonctionner normalement. Ceci est la réutilisation de ce niveau, de nouvelles méthodes, des anciens systèmes, des extensions et de la réutilisation.
AOP (programmation orientée section):
La programmation essentielle est une technologie qui ajoute dynamiquement les fonctions aux programmes sans modifier le code source via un proxy dynamique d'exécution précompilé.
Différence entre OOP et AOP:
POO: L'encapsulation abstraite est réalisée sur les entités et leurs propriétés et comportements du processus de traitement des affaires pour obtenir une division plus claire des unités logiques.
AOP: extrait la logique de coupe croisée dans le processus métier. Il fait face à une certaine étape ou étape du processus pour obtenir l'effet d'isolement de couplage faible entre les parties du processus logique. Ces deux idées de conception ont des différences essentielles dans les objectifs. AOP a réalisé la réutilisation des blocs de code.
Mécanisme de proxy Spring AOP:
1. Si l'objet cible implémente plusieurs interfaces, Spring utilise Java.lang.Reflect.Proxy Class Proxy de JDK.
Avantages: Parce qu'il y a une interface, le système est plus lâche
Inconvénients: créer des interfaces pour chaque classe cible
2. Si l'objet cible n'implémente aucune interface, Spring utilise la bibliothèque CGLIB pour générer une sous-classe de l'objet cible.
Avantages: Parce que la classe proxy et la classe cible sont héritées, il n'est pas nécessaire qu'une interface existe.
Inconvénients: Parce qu'il n'y a pas d'interface utilisée, le couplage du système n'est pas aussi bon que le proxy dynamique à l'aide de JDK.
Utilisation de l'interface Persondao, de la classe Persondaoimpl et de la classe de transaction
Écrire la configuration de ressort
<bean id = "Persondao"> </Ean> <bean id = "Transaction"> </anEn> <aop: config> <! - L'expression de points de point de point détermine la classe cible -> <aop: Pointcut Expression = "Exécution (* cn.qjc.aop.xml.PersondaOIMPl. * (..)" id = "perform" ref = "transaction"> <aop: avant méthode = "beginTransaction" Pointcut-ref = "perform" /> <aop: après-retour méthode = "commit" Pointcut-ref = "perform" /> </ aop: aspect> </aop: config> </ beans>
test
/ ** * Tester Spring Dynamic Proxy * @author qjc * / public class transactionTest {@Test public void TestSave () {ApplicationContext context = new ClassPathXmlApplicationContext ("CN / QJC / AOP / xml / applicationContext.xml"); Persondao Persondao = (Persondao) context.getBean ("Persondao"); Persondao.Saveperson (); }}Principe de printemps AOP
1. Lorsque le récipient à ressort est démarré, deux haricots sont chargés et instanciés.
2.
3. Si le match réussit, créez un objet proxy pour le haricot
4. Lorsque le client utilise Context.getBean pour obtenir un objet, si l'objet a un objet proxy, il renvoie l'objet proxy. S'il n'y a pas d'objet proxy, il renvoie l'objet lui-même.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.