Das Konzept der AOP
AOP: Aspekt-orientierte Programmierung (sachlich orientierte Programmierung), wikipedia erklärt es wie folgt: Aspekt ist ein neuer modularer Mechanismus, der zur Beschreibung von Querschnittsproblemen verwendet wird, die in Objekten, Klassen oder Funktionen verstreut sind. Die Trennung von Querschnittsbedenken von Bedenken ist das Kernkonzept der tangentorientierten Programmierung. Durch die Trennung des Fokus stellt der Code, der spezifische Domänenprobleme löst, unabhängig von der Geschäftslogik. Der Code of Business Logic enthält keine Aufrufe zum Code für bestimmte Domänenprobleme. Die Beziehung zwischen Geschäftslogik und spezifischen Domänenproblemen wird durch Abschnitte eingekapselt und aufrechterhalten, so dass Änderungen, die ursprünglich während der gesamten Anwendung verstreut waren, gut verwaltet werden können. Aus Sicht der AOP können Anwendungen in Querschnittsprobleme und Geschäftslogikcode unterteilt werden. In der tatsächlichen Entwicklung sind diese Querschnittsprobleme häufig direkt in den Geschäftslogikcode eingebettet. Face-orientierte Programmierung besteht darin, das Problem der Trennung von Querschnittsbedenken von der Geschäftslogik zu lösen.
Implementierungsmethode:
Spring verwendet standardmäßig JDK Dynamic Proxy als AOP -Proxy. Der Fehler ist, dass die Zielklasse eine Schnittstelle implementieren muss, andernfalls kann der JDK -Dynamische Proxy nicht verwendet werden. Wenn die Klasse eher eine Klasse als eine Schnittstelle ist, verwendet Spring standardmäßig CGGLIB Proxy. In Bezug auf den Unterschied zwischen den beiden: JDK Dynamic Proxy wird durch den Reflexionsmechanismus von Java implementiert, die Zielklasse muss Schnittstellen implementieren und CGGLIB implementiert Proxy für Klassen. Sein Prinzip besteht darin, eine Unterklasse für die angegebene Zielklasse dynamisch zu generieren und die Verstärkung der Methodeimplementierung zu überschreiben. Da die Vererbung jedoch verwendet wird, kann die endgültige modifizierte Klasse jedoch nicht proxyiert werden.
JDK Dynamic Proxy
JDK Dynamic Proxy generiert dynamisch Klassendateien von Proxy -Klassen basierend auf der von der Zielklasse während des Programmvorgangs implementierten Schnittstelle. Die Verwendung umfasst hauptsächlich zwei Klassen:
InvocationHandler -Schnittstelle: Es bietet eine invoke(Object obj,Method method, Object[] args) für Implementierer, um die entsprechende Proxy -Logikimplementierung bereitzustellen. Eine spezielle Verarbeitung kann für die tatsächliche Implementierung durchgeführt werden, und die Parameter sind
Objekt OBJ: Die Zielklasse, die proxyiert ist
Methodenmethode: Methode der Zielklasse, die ausgeführt werden muss
Objekt [] Argumentation: Parameter der Zielmethode
Proxy -Klasse: Geben Sie eine Methode newProxyInstance (ClassLoader loader, Class[] interfaces, InvocationHandler h) an, um eine dynamische Proxy -Klasse zu erhalten
Beispielcode:
public interface ordersservice {public void createorder (); } public class orderServiceImpl implementiert orderService {@Override public void createorder () {System.out.println ("Reihenfolge erstellen"); }} öffentliche Klasse OrderLogger {public void beecreateorder () {System.out.println ("Before Create Order"); } public void Aftercreateorder () {System.out.println ("After Create Order"); }} Paket com.sl.aop; import java.lang.reflect.invocationHandler; import java.lang.reflect.method; import java.lang.reflect.proxy; public class ServiceProxy Implements InvocationHandler {private Object ZielClass; privater OrderLogger OrderLogger; public ServiceProxy (Objektzielklasse, OrderLogger OrderLogger) {this.targetClass = targetClass; this.orderLogger = orderLogger; } // Proxy Public Object getDynamicproxy () {return proxy.newproxyInstance (targetClass.getClass (). GetClassloader (), // Proxy -Objekt über diesen Klassenloader targetClass.getClass (). // Die dynamische Proxy -Aufrufmethode ist der zugehörige InvocationHandler und führt schließlich die reale Methode über die Invoke -Methode dieses InvocationHandlers} // implementieren Sie die entsprechende Proxy -Logik @Override öffentliches Objekt auf Incoke (Object Proxy, Methode Methode, Object [] Args) aus, die Throwable {this.orderLogger.befeforecreateRecteReorder () ausgeworfen werden. Objektergebnis = methode.invoke (Zielklasse, Argumente); this.orderLogger.afterCreateorder (); Rückgabeergebnis; }}Testklasse:
Paket com.sl.aop; import org.junit.test; public class aoptest {@Test public void testDynamicproxy () {orderServiceImPl ServiceImpl = new orderServiceImpl (); OrderLogger Logger = New OrderLogger (); OrderService service = (orderService) neuer serviceProxy (ServiceImpl, Logger) .GetDynamicProxy (); Service.Createorder (); }}Auslaufergebnisse:
Ich bin eigentlich ein wenig verwirrt, wenn ich diesen Punkt erreiche. Was kehrt Proxy.newProxyInstance() zurück? Wo ist die aufgerufene Methode genannt? Schauen wir uns den JDK -Quellcode an: Sehen Sie, wie der Prozess des DK Dynamic Proxy aussieht:
Rufen Sie Proxy.newProxyInstance()->Proxy.getProxyClass0()->WeakCache.get() gemäß der Funktion im Quellcode an und lokalisieren Sie ihn zuerst.
Weapcache.class:
public v get (k key, p parameter) {objects.requirenonnull (Parameter); explodestaleEntries (); Object Cachekey = CacheKey.ValueOf (Schlüssel, RefQueue); // faul die zweite Ebene Valuesmap für die bestimmte cachekey ConcurrentMap <Objekt, Lieferant <v >> valuesmap = map.get (cachekey) installieren; if (valuesmap == null) {ConcurrentMap <Objekt, Lieferant <v >> oldValuesMap = map.putiFabSent (cachekey, valuesmap = new ConcurrentHasMap <> ()); if (oldValuesMap! = null) {valuesMap = oldValuesMap; }} // subkey erstellen und den möglichen Lieferanten <V> abrufen, der von diesem // subkey aus VALTURSMAP -Objekt subKey = Objects.requirenonnull (subKeyFactory.Apply (Schlüssel, Parameter)) abgerufen wird; Lieferant <V> Lieferant = valuesmap.get (subKey); Werksfabrik = NULL; while (true) {if (Lieferant! if (value! = null) {Rückgabewert; }} // sonst kein Lieferant im Cache // oder ein Lieferant, der NULL zurückgegeben hat (kann ein gelöschtes Cachevalue sein // oder eine Fabrik, die nicht erfolgreich bei der Installation des Cachevalue zu installieren war). } if (Lieferant == null) {Lieferant = valuesMap.putiFabSent (SubKey, Fabrik); if (Lieferant == NULL) {// erfolgreich installierte Fabriklieferant = Fabrik; } // sonst wiederholen mit Gewinnlieferant} else {if (valuesmap.replace (SubKey, Lieferant, Fabrik)) {// erfolgreich ersetzt // CacheEentry / erfolgloses Werk // durch unsere Fabrik -Lieferanten = Fabrik; } else {// Wiederholung mit dem aktuellen Lieferantenlieferanten Lieferanten = valuesmap.get (subKey); }}}} Sie können den Funktionsrückgabewert sehen. und V value = supplier.get(); Lesen Sie es weiter auf und stellen Sie Factory.get()
public synchronized v get () {// serialisieren access // prüfe Lieferanten <V> Lieferant = valuesmap.get (subKey); if (Lieferant! } // sonst still wir (Lieferant == this) // Neuen Wert v value = null erstellen; try {value = objects.requirenonnull (valueFactory.Apply (Schlüssel, Parameter)); } endlich {if (value == null) {// Entfernen Sie uns auf Fehler valueMap.remove (subkey, this); }} // Der einzige Weg, der hier zu erreichen ist, ist mit dem Wert nicht null-Werts! = NULL; // Wickelwert mit Cachevalue (WewReference) Cachevalue <V> cachevalue = neuer Cachevalue <> (Wert); // Versuchen Sie, uns durch Cachegresse zu ersetzen (dies sollte immer erfolgreich sein), wenn (valuesmap.replace (subKey, this, cachevalue)) {// auch in Reverseemap Reverseemap.put (Cachevalue, Boolean.True) einfügen; } else {werfen neuer Assertionerror ("sollte hier nicht erreichen"); } // ersetzt uns erfolgreich durch neues Cachevalue -> Return the Wert //, der von IT zurückgepackt ist; } Rückgabewert; Anschließend direkt die Zuordnungsanweisung anzeigen: value = Objects.requireNonNull(valueFactory.apply(key, parameter));
Was zum Teufel ist ValueFactory?
public weccache (bifunction <k, p,?> subkeyfactory, bifunction <k, p, v> valueFactory) {this.subkeyfactory = Objects.requirenonnull (subKeyFactory); this.ValueFactory = Objects.requirenonnull (ValueFactory); } private statische endgültige schwache Wexcache <Classloader, Klasse <?> [], Klasse <? >> proxyclassCache = new Weapcache <> (new KeyFactory (), New ProxyClassFactory ()); Sie können wissen, dass ValueFactory ein ProxyClassFactory -Objekt ist und direkt ProxyClassFactory. Apply() Methode
public class <??> apply (classloader loader, class <?> [] interfaces) {map <class <?>, boolean> interfaceset = new IdentityHasMap <> (interfaces.length); für (Klasse <?> Intf: Schnittstellen) { / * * Überprüfen Sie, ob der Klasse Loader den Namen dieser * Schnittstelle zu demselben Klassenobjekt auflöst. */ Class <?> InterfaceClass = null; try {interfaceClass = class.forname (intf.getName (), false, lader); } catch (classNotFoundException e) {} if (interfaceClass! } / * * Überprüfen Sie, ob das Klassenobjekt tatsächlich eine * Schnittstelle darstellt. */ if (! interfaceClass.Isersinterface ()) {neue IllegalArgumentException (interfaceClass.getName () + "ist keine Schnittstelle"); } / * * Überprüfen Sie, ob diese Schnittstelle kein Duplikat ist. */ if (interfaceset.put (interfaceClass, boolean.true)! }} String proxypkg = null; // Paket zum Definieren der Proxy -Klasse in int accessFlags = modifier.public | Modifikator.final; / * * Notieren Sie das Paket einer nicht öffentlichen Proxy-Schnittstelle, damit die * Proxy-Klasse im selben Paket definiert wird. Stellen Sie sicher, dass * alle nicht öffentlichen Proxy-Schnittstellen im selben Paket sind. */ for (class <?> intf: interfaces) {int flags = intf.getModifiers (); if (! modificier.ispublic (Flags)) {AccessFlags = modifier.final; String name = intf.getName (); int n = name.lastIndexof ('.'); String pkg = ((n == -1)? "": Name.substring (0, n + 1)); if (proxypkg == null) {proxypkg = pkg; } else if (! pkg.equals (proxypkg)) {werfen Sie neue illegalArgumentException ("nicht öffentliche Schnittstellen aus verschiedenen Paketen"); }}}} if (proxypkg == null) {// Wenn keine nicht öffentlichen Proxy-Schnittstellen, verwenden Sie com.sun.proxy paket proxypkg = reflectil.proxy_package + ". } / * * Wählen Sie einen Namen, damit die Proxy -Klasse generiert werden kann. */ long num = nextUniqueNumber.getandIncrement (); String proxyname = proxypkg + proxyclassnameprefix + num; / * * Generieren Sie die angegebene Proxy -Klasse. */ byte [] proxyclassfile = proxygenerator.generateProxyClass (Proxyname, Schnittstellen, AccessFlags); try {return defeclass0 (Loader, Proxyname, ProxyClassfile, 0, proxyClassfile.length); } catch (classformaterror e) { / * * Ein klassifischer Formaterror bedeutet, dass (Bugs im * Proxy -Klassengenerierungscode) einen anderen * ungültigen Aspekt der Argumente, die der Proxy * -Klasserstellung geliefert wurden (z. B. virtuelle Maschinenbeschränkungen * überschritten wurden). */ werfen neue illegalArgumentException (e.toString ()); }}}Zeichnen Sie direkt die wichtigsten Punkte:
byte [] proxyclassfile = proxygenerator.generateProxyClass (Proxyname, Schnittstellen, AccessFlags); return defeclass0 (Loader, Proxyname, ProxyClassfile, 0, Proxyclassfile.length);
Das Aufrufen ProxyGenerator.generateProxyClass generiert endlich dynamisch eine Proxy -Klasse, aber es scheint, dass nirgends nirgends als Invoke bezeichnet wird. Siehe Artikel csdn: //www.vevb.com/article/118935.htm. Der Testcode lautet wie folgt:
public class aoptest {@test public void testDynamicProxy () {orderServiceImpl ServiceImpl = new orderServiceImpl (); OrderLogger Logger = New OrderLogger (); OrderService service = (orderService) neuer serviceProxy (ServiceImpl, Logger) .GetDynamicProxy (); Service.Createorder (); // dynamische Proxy -Klasse -Bytecode createReProxyClassfile () ausgeben; } private statische void createReProxyClassFile () {String name = "proxyObject"; byte [] data = proxygenerator.generateProxyClass (Name, neue Klasse [] {orderService.class}); FileOutputStream out = null; try {out = new FileOutputStream (Name+". Klasse"); System.out.println ((neue Datei ("Hallo"). GetAbsolutepath ()); out.write (Daten); } catch (FilenotFoundException e) {e.printstacktrace (); } catch (ioException e) {e.printstacktrace (); } endlich {if (null! = out) try {out.close (); } catch (ioException e) {e.printstacktrace (); }}}}}}Verwenden Sie das Java Decompiler -Tool, um diese Binärklassendatei zu dekompilieren:
Spezifische dynamische Proxy -Klasse ProxyObject.java:
import com.sl.aop.orderservice; import java.lang.reflect.invocationHandler; import java.lang.reflect.method; import Java.lang.reflect.Proxy import Java.lang.Lang.Reflect.undechlaredToWablexception. private statische Methode M2; private statische Methode M3; private statische Methode M0; public proxyObject (invocationHandler paramInvocationHandler) {Super (paramInvocationHandler); } public Final Boolean Equals (Object ParamObject) {try {return ((boolean) this.h.invoke (this, m1, neues Objekt [] {paramObject})). booleanValue (); } catch (Fehler | RunTimeException localError) {localError werfen; } catch (Throwable Local throwable) {werfen neu ohne offenkundigem Drowablexception (Local throwable); }} public Final String toString () {try {return (string) this.h.invoke (this, m2, null); } catch (Fehler | RunTimeException localError) {localError werfen; } catch (Throwable Local throwable) {werfen neu ohne offenkundigem Drowablexception (Local throwable); }} public Final void createorder () {try {this.h.invoke (this, m3, null); zurückkehren; } catch (Fehler | RunTimeException localError) {localError werfen; } catch (Throwable Local throwable) {werfen neu ohne offenkundigem Drowablexception (Local throwable); }} public Final int hashCode () {try {return ((Integer) this.h.invoke (this, m0, null)). intValue (); } catch (Fehler | RunTimeException localError) {localError werfen; } catch (Throwable Local throwable) {werfen neu ohne offenkundigem Drowablexception (Local throwable); }} static {try {m1 = class.forname ("java.lang.object"). getMethod ("Equals", New Class [] {class.forname ("java.lang.Object")}); m2 = class.Forname ("java.lang.object"). getMethod ("tostring", neue Klasse [0]); M3 = class.Forname ("com.sl.aop.orderservice"). getMethod ("createorder", neue Klasse [0]); M0 = class.Forname ("java.lang.object"). getMethod ("HashCode", neue Klasse [0]); zurückkehren; } catch (NoSuchMethodException localnosuchMethodException) {neue noSuchMethoderror werfen (localnosuchMethodException.getMessage ()); } catch (classNotFoundException localClassNotFoundException) {neue noclassDeffoundError werfen (localClassNotFoundException.getMessage ()); }}Endlich den Teil über Invoke gesehen:
public Final void createorder () {try {this.h.invoke (this, m3, null); zurückkehren; } catch (Fehler | RunTimeException localError) {localError werfen; } catch (Throwable Local throwable) {werfen neu ohne offenkundigem Drowablexception (Local throwable); }}Tatsächlich erbt die dynamische Proxy -Klasse von Proxy und implementiert die von der Zielklasse geerbte Schnittstelle. Die Invoke -Methode wird in der Methode createorder aufgerufen, die die Implantation der Schnittlogik implantiert. Hier beantworten wir auch eine Frage, warum die Zielklasse des JDK -Dynamischen Proxy die Schnittstelle implementieren muss, da die Proxy -Klasse tatsächlich auf den Schnittstellenproxy und nicht auf die Klasse ausgerichtet ist. Die dynamische Proxy -Klasse erbt sich von Proxy, und Java lässt nicht mehrfache Vererbung zu. Die dynamische Proxy -Klasse und die Zielklasse implementieren tatsächlich die Schnittstellen. Die Proxy -Klasse erkennt den Anruf bei der Zielklassenmethode über InvocationHandler.invoke.
CGGLIB Dynamic Proxy
Der CGGLIB-Proxy verwendet ein Bytecode-Verarbeitungs-Framework-ASM, um Bytecode umzuwandeln und neue Klassen zu generieren. Methodenabnehmungstechniken in Unterklassen, um alle übergeordneten Klassenmethoden abzufangen, um die Überschneidungslogik zu implementieren, die effizienter als der JDK-Dynamische Proxy mithilfe der Reflexionstechnologie ist. Da das Prinzip von CGlib darin besteht, für die Zielklasse dynamisch Unterklassen -Proxyklassen zu erzeugen, kann es nicht für Methoden, die als endgültig deklariert sind, ausgezeichnet werden. Die Verwendung umfasst hauptsächlich zwei Kategorien:
MethodInterceptor -Schnittstelle: Diese Schnittstelle bietet eine Methode intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) hauptsächlich zum Abfangen des Rufnetzes der Zielklassenmethoden verwendet wird.
Objekt arg0,: Die Zielklasse, die ausgetauscht wird
Methode Arg1, Delegiermethode
Objekt [] Arg2, Methodenparameter
MethodProxy Arg3: MethodProxy -Objekt der Proxy -Methode
Enhancer -Klasse: Wird verwendet, um Proxy -Klasse zu erstellen
Beispiel:
Implementieren Sie die MethodInteceTor -Schnittstelle. Wenn die Proxy -Klasse eine Methode aufruft, ruft CGLIB die MethodeInterceptor -Schnittstellen -Intercept -Methode zurück und webt damit die Oberflächenlogik.
Paket com.sl.aop; import java.lang.reflect.method; import org.springframework.cglib.proxy.enhancer; import org.springframework.cglib.proxy.Methodinterceptor; {private Objektzielklasse; privater OrderLogger OrderLogger; public cglibServiceProxy (Objektzielklasse, OrderLogger OrderLogger) {this.targetClass = targetClass; this.orderLogger = orderLogger; } / *** Erstellen Sie ein Proxy -Objekt** / public Object getInstance () {Enhancer Enhancer = new Enhancer (); // Setzen Sie die Zielklasse (Klasse, die proxyed werden muss) Enhancer.setsuperClass (this.targetClass.getClass ()); // Callback -Methode Enhancer.SetCallback (this); // Proxy -Objekt -Rückgabeverstärkung erstellen.create (); } / *** Abfangen aller Zielklassenmethoden** / @Override öffentliches Objekt Intercept (Object arg0, method arg1, object [] arg2, methodProxy arg3) löst Throwable {OrderLogger.beFerecrateReorder () aus; Objekt O1 = arg3.Invokesuper (arg0, arg2); OrderLogger.AfterCreateorder (); Rückkehr O1; }}Testmethode:
public void testDynamicproxy () {System.setProperty (DebuggingClasswriter.Debug_location_property, "d: // class"); OrderServiceImPl ServiceImpl = new orderServiceImpl (); OrderLogger Logger = New OrderLogger (); CGlibServiceProxy proxy = new CglibServiceProxy (ServiceImpl, Logger); // Erstellen Sie eine Proxy -Klasse, indem Sie Unterklassen orderServiceImpl proxyimp = (orderServiceImpl) proxy.getInstance () generieren; proxyimp.createorder (); }Ergebnis:
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D://class"); Ausgabe der dynamischen Proxy -Klasse CGGLIB in das angegebene Verzeichnis, dekompilieren Sie das wahre Gesicht der Proxy -Klasse:
Paket com.sl.aop; import com.sl.aop.orderserviceImpl; import Java.lang.reflect.method; import org.springframework.cglib.core.reflectils; org.springFramework.cglib.proxy.factory; import org.springframework.cglib.proxy.methodinterceptor; import org.spingframework Cglib $ gebunden; öffentliches statisches Objekt cGlib $ factory_data; private statische endgültige ThreadLocal cGlib $ thread_callbacks; privater statischer endgültiger Rückruf [] cGlib $ static_callbacks; private methodInterceptor cglib $ callback_0; privates statisches Objekt cGlib $ callback_filter; private statische endgültige Methode cGlib $ createorder $ 0 $ Methode; private statische endgültige Methode Proxy Cglib $ createorder $ 0 $ Proxy; privates statisches endgültiges Objekt [] cGlib $ leereArgs; private statische endgültige Methode cGlib $ gleich $ 1 $ Methode; Private statische endgültige MethodeProxy CGlib $ Equals $ 1 $ $ Proxy; private statische endgültige Methode cGlib $ toString $ 2 $ Methode; private statische endgültige MethodeProxy cGlib $ toString $ 2 $ Proxy; private statische endgültige Methode cGlib $ HashCode $ 3 $ Methode; private statische endgültige MethodeProxy Cglib $ HashCode $ 3 $ Proxy; Private statische endgültige Methode $ Clone $ 4 $ Methode; private statische endgültige MethodeProxy CGlib $ Clone $ 4 $ Proxy; static void cglib $ statichook1 () {cglib $ thread_callbacks = new threadLocal (); Cglib $ leerArgs = neues Objekt [0]; Klasse var0 = class.Forname ("com.sl.aop.orderserviceImpl Klasse var1; Methode [] var10000 = reflectUtils.findMethods (neue String [] {"Equals", "(Ljava/Lang/Object;) Z", "ToString", () ljava/lang/String; Class.forname ("java.lang.object")). GetDeclaredMethods ()); Cglib $ Equals $ 1 $ method = var10000 [0]; CGlib $ Equals $ 1 $ proxy = methodProxy.create (var1, var0, "(Ljava/Lang/Objekt;) Z", "Equals", "Cglib $ Equals $ 1"); Cglib $ toString $ 2 $ method = var10000 [1]; Cglib $ toString $ 2 $ proxy = methodProxy.create (var1, var0, "() ljava/Lang/String;", "toString", "Cglib $ toString $ 2"); Cglib $ HashCode $ 3 $ method = var10000 [2]; Cglib $ HashCode $ 3 $ $ proxy = methodProxy.create (var1, var0, "() i", "HashCode", "Cglib $ HashCode $ 3"); Cglib $ clone $ 4 $ method = var10000 [3]; Cglib $ clone $ 4 $ proxy = methodProxy.create (var1, var0, "() ljava/Lang/Objekt;", "Clone", "Cglib $ Clone $ 4"); CGlib $ createorder $ 0 $ method = reflectUtils.findMethods (neuer String [] {"createorder", "() v"}, (var1 = class.ForName ("com.sl.aop.OrterserviceImpl")). GetDeclaredMethods ()) [0]; CGlib $ createorder $ 0 $ proxy = methodProxy.create (var1, var0, "() v", "createorder", "cglib $ createorder $ 0"); } Finale void cglib $ createorder $ 0 () {Super.Createorder (); } public Final void createorder () {methodInterceptor var10000 = this.cglib $ callback_0; if (this.cglib $ callback_0 == null) {cglib $ bind_callbacks (this); var10000 = this.cglib $ callback_0; } if (var10000! } else {super.createorder (); }} endgültig boolean cGlib $ Equals $ 1 (Objekt var1) {return Super.equals (var1); } public Final Boolean Equals (Object var1) {methodInteceTor var10000 = this.cglib $ callback_0; if (this.cglib $ callback_0 == null) {cglib $ bind_callbacks (this); var10000 = this.cglib $ callback_0; } if (var10000! return var2 == null? false: ((boolean) var2) .booleanValue (); } else {return Super.equals (var1); }} Finale String cGlib $ toString $ 2 () {return Super.toString (); } public Final String toString () {methodInterceptor var10000 = this.cglib $ callback_0; if (this.cglib $ callback_0 == null) {cglib $ bind_callbacks (this); var10000 = this.cglib $ callback_0; } return var10000! = null? (String) var10000.Intercept (this, cGlib $ toString $ 2 $ Methode, cGlib $ leereArgs, cglib $ toString $ 2 $ proxy): Super.toString (); } Finale int cGlib $ HashCode $ 3 () {return Super.hashCode (); } public Final int HashCode () {methodInterceptor var10000 = this.cglib $ callback_0; if (this.cglib $ callback_0 == null) {cglib $ bind_callbacks (this); var10000 = this.cglib $ callback_0; } if (var10000! = null) {Object var1 = var10000.Intercept (this, cGlib $ HashCode $ 3 $ Methode, cGlib $ leereArgs, cglib $ HashCode $ 3 $ proxy); return var1 == null? 0: ((number) var1) .IntValue (); } else {return Super.hashCode (); }} endgültiges Objekt cGlib $ clone $ 4 () löscht ClonenotsupportedException {return Super.clone (); } Protected Final Object Clone () löscht ClonenotsupportedException {methodInterceptor var10000 = this.cglib $ callback_0; if (this.cglib $ callback_0 == null) {cglib $ bind_callbacks (this); var10000 = this.cglib $ callback_0; } return var10000! = null? var10000.Intercept (this, cGlib $ clone $ 4 $ Methode, cGlib $ leereArgs, cglib $ clone $ 4 $ proxy): Super.clone (); } public static methodProxy cglib $ findMethodproxy (Signature var0) {String var10000 = var0.toString (); Switch (var10000.hashcode ()) {case -2138148221: if (var10000.equals ("createorder () v")) {return cGlib $ createorder $ 0 $ proxy; } brechen; Fall -508378822: if (var10000.equals ("Clone () ljava/lang/Objekt;")) {return cGlib $ clone $ $ proxy; } brechen; Fall 1826985398: if (var10000.equals ("Equals (Ljava/Lang/Objekt;) Z")) {return cGlib $ Equals $ $ $ proxy; } brechen; Fall 1913648695: if (var10000.equals ("toString () ljava/Lang/String;"))) {return cGlib $ toString $ 2 $ Proxy; } brechen; Fall 1984935277: if (var10000.equals ("HashCode () i")) {return cGlib $ HashCode $ 3 $ Proxy; }} return null; } public orderServiceImpl $$ EnhancerByCglib $$ 17779AA4 () {cglib $ bind_callbacks (this); } public static void cGlib $ set_thread_callbacks (callback [] var0) {cglib $ thread_callbacks.set (var0); } public static void cglib $ set_static_callbacks (Callback [] var0) {cglib $ static_callbacks = var0; } private statische endgültige void cglib $ bind_callbacks (Objekt var0) {orderServiceImpl $$ EnhancerByCglib $$ 17779AA4 var1 = (orderServiceImpl $$ EnhancerByCglib $$ 17779AA4) var0; if (! var1.cglib $ band) {var1.cglib $ bound = true; Objekt var10000 = cGlib $ thread_callbacks.get (); if (var10000 == null) {var10000 = cglib $ static_callbacks; if (cglib $ static_callbacks == null) {return; }} var1.cglib $ callback_0 = (methodInterceptor) ((callback []) var10000) [0]; }} öffentliches Objekt NewInstance (Callback [] var1) {cglib $ set_thread_callbacks (var1); OrderServiceImpl $$ EnhancerByCGlib $$ 17779AA4 VAR10000 = NEUER orderServiceImpl $$ EnhancerByCGlib $$ 17779AA4 (); Cglib $ set_thread_callbacks ((callback []) null); return var10000; } öffentliches Objekt NewInstance (Callback var1) {cglib $ set_thread_callbacks (neuer Callback [] {var1}); OrderServiceImpl $$ EnhancerByCGlib $$ 17779AA4 VAR10000 = NEUER orderServiceImpl $$ EnhancerByCGlib $$ 17779AA4 (); Cglib $ set_thread_callbacks ((callback []) null); return var10000; } public Object NewInstance (class [] var1, Object [] var2, callback [] var3) {cglib $ set_thread_callbacks (var3); OrderServiceImpl $$ EnhancerByCGlib $$ 17779AA4 VAR10000 = NEUER orderServiceImpl $$ EnhancerByCGlib $$ 17779AA4; Switch (var1.length) {case 0: var10000. <init> (); Cglib $ set_thread_callbacks ((callback []) null); return var10000; Standard: Werfen Sie neue IllegalArgumentException ("Konstruktor nicht gefunden"); }} public callback getCallback (int var1) {cglib $ bind_callbacks (this); MethodInterceptor var10000; Switch (var1) {case 0: var10000 = this.cglib $ callback_0; brechen; Standard: var10000 = null; } return var10000; } public void setCallback (int var1, callback var2) {switch (var1) {case 0: this.cglib $ callback_0 = (methodInterceptor) var2; Standard:}} public callback [] getCallbacks () {cglib $ bind_callbacks (this); RECHTEN SIE NEUER CALLBACK [] {this.cglib $ callback_0}; } public void setCallbacks (callback [] var1) {this.cglib $ callback_0 = (methodInterceptor) var1 [0]; } static {cGlib $ Statichook1 (); }}Im obigen Code können Sie sehen, dass die Proxy -Klasse orderServiceImpl $$ EnhancerByCGlib $$ 17779AAA4 die Zielklasse orderServiceImpl erbt und die Schnittstellenfabrik implementiert. In der Proxy -Klasse werden zwei Methoden CGlib $ createorder $ 0 und createorder generiert:
Die Methode cGlib $ createorder $ 0 ruft direkt das supper.createOrder der Zielklasse auf. Createorder
Mit der Createorder -Methode wird zunächst gezählt, ob der Rückruf der MethodeInterceptor -Schnittstelle implementiert ist. Wenn es vorhanden ist, wird die MethodeInterceptor -Schnittstellen -Intercept -Methode aufgerufen. Gemäß der vorherigen Implementierung wird der Anruf bei der Zielmethode implementiert. Object o1 = arg3.invokeSuper(arg0, arg2) wird implementiert. Der Invocesuper ist eigentlich CGLIB$createOrder$0() -Methode der Proxy -Klasse, die direkt aufgerufen wird, und die Zielklasse Createorder wird schließlich aufgerufen.
Vergleich von zwei Agenten
JDK Dynamischer Proxy:
Die Proxy -Klasse und die Delegierteklasse implementieren dieselbe Schnittstelle. Es implementiert hauptsächlich den InvocationHandler durch die Proxy -Klasse und schreibt die Invoke -Methode um, um dynamisches Proxying durchzuführen. Die Methode wird in der Invoke -Methode verbessert. Die Vorteile der Methode: Es ist keine hartcodierte Schnittstelle erforderlich, und die Code-Wiederverwendungsrate ist hoch. Nachteile: Nur die Delegierteklasse, die von der Schnittstelle implementiert werden kann
CGGLIB Dynamic Proxy:
Die Proxy-Klasse nimmt die Delegierteklasse als übergeordnete Klasse an und erstellt zwei Methoden für die nicht-Final-Delegierten-Methoden. Eine ist dieselbe Methode wie die Signatur der Delegiertenmethode, die die Delegate -Methode über Super in der Methode aufruft. Die andere ist die Methode, die für die Proxy -Klasse einzigartig ist. In der Proxy -Methode bestimmt es, ob es ein Objekt gibt, das die MethodInterceptor -Schnittstelle implementiert. Wenn es vorhanden ist, wird die Intercept -Methode aufgerufen, um die Delegate -Methode zu proxy. Vorteile: Sie kann den Betrieb der Klasse oder Schnittstelle zur Laufzeit verbessern, und die Delegierteklasse muss die Schnittstelle nicht implementieren. Nachteile: Es kann die endgültige Klasse und die endgültige Methode nicht in Anspruch nehmen.
Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Referenzwert für das Studium oder die Arbeit eines jeden hat. Wenn Sie Fragen haben, können Sie eine Nachricht zur Kommunikation überlassen. Vielen Dank für Ihre Unterstützung bei Wulin.com.