Konsep AOP
AOP: Pemrograman berorientasi aspek (pemrograman berorientasi sectional), Wikipedia menjelaskannya sebagai berikut: Aspek adalah mekanisme modular baru yang digunakan untuk menggambarkan masalah cross-sectional yang tersebar dalam objek, kelas atau fungsi. Memisahkan keprihatinan cross-sectional dari kekhawatiran adalah konsep inti pemrograman yang berorientasi pada tangen. Memisahkan fokus membuat kode yang memecahkan masalah domain tertentu terlepas dari logika bisnis. Kode Logika Bisnis tidak berisi panggilan ke kode untuk masalah domain tertentu. Hubungan antara logika bisnis dan masalah domain spesifik dienkapsulasi dan dipelihara melalui bagian, sehingga perubahan yang awalnya tersebar di seluruh aplikasi dapat dikelola dengan baik. Dari perspektif AOP, aplikasi dapat dibagi menjadi masalah cross-sectional dan kode logika bisnis. Dalam pengembangan aktual, kekhawatiran cross-sectional ini sering secara langsung tertanam dalam kode logika bisnis. Pemrograman yang berorientasi pada wajah adalah untuk memecahkan masalah memisahkan masalah cross-sectional dari logika bisnis.
Metode Implementasi:
Spring menggunakan proxy dinamis JDK sebagai proxy AOP secara default. Kelemahannya adalah bahwa kelas target harus mengimplementasikan antarmuka, jika tidak, proxy dinamis JDK tidak dapat digunakan. Jika kelas adalah kelas daripada antarmuka, Spring akan menggunakan proxy CGLIB secara default. Mengenai perbedaan antara keduanya: proxy dinamis JDK diimplementasikan melalui mekanisme refleksi Java, kelas target harus mengimplementasikan antarmuka, dan CGLIB mengimplementasikan proxy untuk kelas. Prinsipnya adalah untuk secara dinamis menghasilkan subclass untuk kelas target yang ditentukan dan mengesampingkan peningkatan peningkatan implementasi metode, tetapi karena warisan digunakan, kelas akhir yang dimodifikasi tidak dapat dikenakan.
JDK Dynamic Proxy
JDK Dynamic Proxy secara dinamis menghasilkan file kelas kelas proxy berdasarkan antarmuka yang diimplementasikan oleh kelas target selama operasi program. Penggunaannya terutama melibatkan dua kelas:
InvocationHandler Interface: Ini menyediakan metode invoke(Object obj,Method method, Object[] args) untuk pelaksana untuk menyediakan implementasi logika proxy yang sesuai. Beberapa pemrosesan khusus dapat dilakukan pada implementasi aktual, dan parameternya
Objek OBJ: Kelas target yang proxyed
Metode Metode: Metode kelas target yang perlu dieksekusi
Objek [] args: parameter metode target
Kelas Proxy: Berikan metode newProxyInstance (ClassLoader loader, Class[] interfaces, InvocationHandler h) untuk mendapatkan kelas proxy dinamis
Kode contoh:
Pesanan Antarmuka Publik {public void createOrder (); } Public Class OrderServiceImpl mengimplementasikan Pesanan Urutan {@Override public void createOrder () {System.out.println ("Membuat pesanan"); }} Public Class OrderLogger {public void beforecreateOrder () {System.out.println ("Sebelum membuat pesanan"); } public void afterCreateOrder () {System.out.println ("Setelah membuat pesanan"); }} Paket com.sl.aop; impor java.lang.reflect.invocationHandler; import java.lang.reflect.method; impor java.lang.reflect.proxy; serviceproxy kelas publik mengimplementasikan doa doa doa {private objek target classclass; Orderlogger Private Logger; Public ServiceProxy (Object TargetClass, OrderLogger OrderLogger) {this.targetClass = TargetClass; this.orderlogger = orderlogger; } // Dapatkan objek publik proxy getDynamicProxy () {return proxy.newproxyInstance (targetClass.getClass (). GetClassLoader (), // Buat objek proxy melalui classloader targetClass.getClass (). // Metode panggilan proxy dinamis adalah InvocationHandler terkait, dan akhirnya menjalankan metode nyata melalui metode Invoke dari Handller ini} // Implementasikan logika proxy yang sesuai @Override objek publik Invoke (objek proxy, metode metode, objek [] args) melempar lemparan {this.orderger.beforeCreate (); Hasil Objek = Method.Invoke (TargetClass, ARGS); this.orderlogger.AfterCreateOrder (); hasil pengembalian; }}Kelas Tes:
Paket com.sl.aop; impor org.junit.test; kelas publik aoptest {@test public void testdynamicproxy () {orderserviceImpl serviceImpl = new OrderServiceImpl (); OrderLogger Logger = New OrderLogger (); Layanan Pesanan = (OrderService) ServiceProxy baru (ServiceImpl, Logger) .getDynamicProxy (); service.createOrder (); }}Hasil Menjalankan:
Saya sebenarnya sedikit bingung ketika mencapai titik ini. Apa yang dikembalikan Proxy.newProxyInstance() ? Di mana metode Invoke dipanggil? Mari kita lihat Kode Sumber JDK: Lihat seperti apa proses proxy dinamis DK:
Hubungi Proxy.newProxyInstance()->Proxy.getProxyClass0()->WeakCache.get() sesuai dengan fungsi di dalam kode sumber, dan pertama-tama temukannya
Lemah Lemah: Kelas:
public v get (K key, parameter p) {objects.requirenonnull (parameter); Expungestaleentries (); Objek CacheKey = CacheKey.VALUEOF (Key, REFQUEUE); // instal malas level 2ndMap untuk CacheKey concurrentMap tertentu <objek, pemasok <v>> valuesmap = map.get (CacheKey); if (valuesmap == null) {concurrentMap <objek, pemasok <v>> oldvaluesmap = map.putifabsent (cacheKey, valuesmap = concurrenthashmap baru <> ()); if (oldValuesMap! = null) {valuesmap = oldValuesMap; }} // Buat subkey dan ambil kemungkinan pemasok <v> yang disimpan oleh // subkey dari valuesmap objek subkey = objects.requirenonnull (subkeyfactory.apply (key, parameter)); Pemasok <v> pemasok = valuesmap.get (subkey); Pabrik Pabrik = NULL; while (true) {if (pemasok! = null) {// pemasok mungkin merupakan pabrik atau cachevalue <v> instance v value = suplier.get (); if (value! = null) {nilai kembali; }} // Jika tidak ada pemasok dalam cache // atau pemasok yang mengembalikan null (bisa menjadi cachevalue yang dibersihkan // atau pabrik yang tidak berhasil memasang cachevalue) // dengan malas membangun pabrik jika (pabrik == null) {pabrik = pabrik baru (kunci, parameter, subkey, nilai nilai); } if (pemasok == NULL) {Suplier = valuesmap.putifabsent (subkey, factory); if (pemasok == null) {// berhasil menginstal pemasok pabrik = pabrik; } // Lain coba lagi dengan pemasok pemenang} else {if (valuesmap.replace (subkey, pemasok, pabrik)) {// berhasil diganti // cacheentry / pabrik yang tidak berhasil // dengan pemasok pabrik kami = pabrik; } else {// coba lagi dengan pemasok pemasok saat ini pemasok = valuesmap.get (subkey); }}}} Anda dapat melihat nilai fungsi pengembalian fungsi; dan V value = supplier.get(); Terus membacanya dan menemukan bahwa makan malam = pabrik sebenarnya adalah objek pabrik, jadi terus lihat metode Factory.get()
Public Synchronized v get () {// Serialize Access // periksa ulang pemasok <V> pemasok = valuesmap.get (subkey); if (pemasok! = this) {// Sesuatu berubah saat kami menunggu: // Mungkin kami digantikan oleh cachevalue // atau dihapus karena kegagalan -> // return null untuk menandakan weastcache.get () untuk mencoba kembali // loop return null; } // else still us (pemasok == this) // buat nilai v baru v nilai = null; coba {value = objects.requirenonnull (valueFactory.Apply (key, parameter)); } akhirnya {if (value == null) {// hapus kami pada nilai kegagalanMap.remove (subkey, this); }} // Satu-satunya jalur untuk dijangkau di sini adalah dengan nilai non-null nilai asert! = null; // Nilai Bungkus dengan Cachevalue (Lemah Referensi) Cachevalue <V> Cachevalue = Cachevalue Baru <> (nilai); // Coba ganti kita dengan cachevalue (ini harus selalu berhasil) if (valuesmap.replace (subkey, this, cachevalue)) {// dimasukkan ke reversemap reversemap.put (cachevalue, boolean.true); } else {throw new AssertionError ("tidak boleh mencapai di sini"); } // berhasil menggantikan kami dengan cachevalue baru -> mengembalikan nilai // dibungkus dengan nilai pengembaliannya; } Nilai pengembalian; kemudian langsung lihat pernyataan penugasan: value = Objects.requireNonNull(valueFactory.apply(key, parameter));
Apa itu penilai itu?
Public lovercache (bifunction <k, p,?> subkeyfactory, bifunction <k, p, v> valueFactory) {this.subkeyfactory = objects.requirenonnull (subkeyfactory); this.valueFactory = objects.requirenonnull (valueFactory); } private static final weakcache <classloader, class <?> [], class <? >> ProxyClassCache = New Weakcache <> (KeyFactory baru (), New ProxyClassFactory ()); Anda dapat mengetahui bahwa ValueFactory adalah objek tipe proxyclassFactory, dan secara langsung melihat ProxyClassFactory. Apply() metode
kelas publik <?> Terapkan (classloader loader, class <?> [] antarmuka) {peta <class <?>, boolean> antarmuka = identityHashMap baru <> (antarmuka.length); untuk (class <?> intf: antarmuka) { / * * Pastikan bahwa class loader menyelesaikan nama antarmuka * ini ke objek kelas yang sama. */ Class <?> InterfaceClass = null; coba {antarmukaclass = class.forname (intf.getName (), false, loader); } catch (classNotFoundException e) {} if (interfaceClass! = intf) {lempar baru ilegalargumentException (intf + "tidak terlihat dari class loader"); } / * * Pastikan bahwa objek kelas sebenarnya mewakili antarmuka *. */ if (! InterfaceClass.isInterface ()) {lempar baru IllegalArgumentException (InterfaceClass.getName () + "bukan antarmuka"); } / * * Pastikan antarmuka ini bukan duplikat. */ if (interfaceset.put (antarmukaclass, boolean.true)! = null) {lempar new IllegalArgumentException ("Antarmuka berulang:" + interfaceClass.getName ()); }} String proxypkg = null; // Paket untuk mendefinisikan kelas proxy di int accessFlags = modifier.public | Modifier.Final; / * * Rekam paket antarmuka proxy non-publik sehingga kelas * proxy akan didefinisikan dalam paket yang sama. Verifikasi bahwa * semua antarmuka proxy non-publik berada dalam paket yang sama. */ for (class <?> intf: antarmuka) {int flags = intf.getModifiers (); if (! Modifier.ispublic (flags)) {AccessFlags = Modifier.Final; Name string = intf.getName (); int n = name.LastIndexOf ('.'); String pkg = ((n == -1)? "": Name.substring (0, n + 1)); if (proxypkg == null) {proxypkg = pkg; } lain jika (! pkg.equals (proxypkg)) {lempar baru ilegalargumentException ("antarmuka non-publik dari paket yang berbeda"); }}}} if (proxypkg == null) {// Jika tidak ada antarmuka proxy non-publik, gunakan paket com.sun.proxy proxypkg = reflectutil.proxy_package + "."; } / * * Pilih nama untuk dihasilkan oleh kelas proxy. */ long num = nextUliquenumber.getAndIncrement (); String proxyname = proxypkg + proxyclassnameprefix + num; / * * Hasilkan kelas proxy yang ditentukan. */ byte [] proxyclassFile = proxygenerator.generateProxyClass (proxyname, antarmuka, accessFlags); coba {return Defineclass0 (loader, proxyname, proxyclassfile, 0, proxyclassfile.length); } catch (ClassFormaterRor e) { / * * ClassFormaterRor di sini berarti bahwa (kecuali bug dalam kode pembuatan kelas * proxy) ada beberapa aspek * tidak valid lainnya dari argumen yang dipasok ke pembuatan kelas proxy * (seperti batasan mesin virtual * terlampaui). */ melempar IllegalArgumentException baru (e.tostring ()); }}}Langsung menggambar poin -poin kunci:
byte [] proxyclassFile = proxygenerator.generateProxyClass (proxyname, antarmuka, accessFlags); return defineclass0 (loader, proxyname, proxyclassfile, 0, proxyclassfile.length);
Memanggil ProxyGenerator.generateProxyClass akhirnya secara dinamis menghasilkan kelas proxy, tetapi tampaknya tidak ada tempat yang ditemukan disebut Invoke; Lihat Artikel CSDN: //www.vevb.com/article/118935.htm, cobalah untuk menghasilkan bytecode biner yang dihasilkan secara dinamis secara lokal dan mendekompilasi untuk melihat apa itu. Kode tes adalah sebagai berikut:
kelas publik aoptest {@test public void testdynamicproxy () {orderServiceImpl serviceImpl = new OrderServiceImpl (); OrderLogger Logger = New OrderLogger (); Layanan Pesanan = (OrderService) ServiceProxy baru (ServiceImpl, Logger) .getDynamicProxy (); service.createOrder (); // output kelas proxy dinamis bytecode createProxyClassFile (); } private static void createProxyClassFile () {string name = "proxyObject"; byte [] data = proxygenerator.generateProxyClass (nama, kelas baru [] {orderservice.class}); FileOutputStream out = null; coba {out = new fileoutputStream (name+". class"); System.out.println ((file baru ("halo")). GetAbsolutePath ()); out.write (data); } catch (FileNotFoundException e) {e.printstacktrace (); } catch (ioException e) {e.printstacktrace (); } akhirnya {if (null! = out) coba {out.close (); } catch (ioException e) {e.printstacktrace (); }}}}}}Gunakan alat Java Decompiler untuk mendekompilasi file kelas biner ini:
Kelas proxy proxy dinamis spesifik proxyobject.java:
Impor com.sl.aop.orderService; impor java.lang.reflect.invocationHandler; impor java.lang.reflect.method; import java.lang.Reflect.proxy; Impor final public. M1; metode statis pribadi m2; Metode statis pribadi M3; Metode Statis Pribadi M0; Public ProxyObject (InvocationHandler ParamInVocationHandler) {super (paramInvocationHandler); } public final boolean sama (objek paramObject) {coba {return ((boolean) this.h.invoke (ini, m1, objek baru [] {paramoBject})). booleanValue (); } catch (error | runimeException localError) {throw localError; } Catch (Throwable LocalThrowable) {lempar New UndeclaredthrowableException (Localthrowable); }} public final string toString () {coba {return (string) this.h.invoke (this, m2, null); } catch (error | runimeException localError) {throw localError; } Catch (Throwable LocalThrowable) {lempar New UndeclaredthrowableException (Localthrowable); }} public final void createOrder () {coba {this.h.invoke (this, m3, null); kembali; } catch (error | runimeException localError) {throw localError; } Catch (Throwable LocalThrowable) {lempar New UndeclaredthrowableException (Localthrowable); }} public final int hashCode () {coba {return ((integer) this.h.invoke (ini, m0, null)). intvalue (); } catch (error | runimeException localError) {throw localError; } Catch (Throwable LocalThrowable) {lempar New UndeclaredthrowableException (Localthrowable); }} static {try {m1 = class.forname ("java.lang.object"). getMethod ("sama", kelas baru [] {class.forname ("java.lang.object")}); m2 = class.forname ("java.lang.object"). getMethod ("tostring", kelas baru [0]); m3 = class.forname ("com.sl.aop.orderService"). getMethod ("createOrder", kelas baru [0]); m0 = class.forname ("java.lang.object"). getMethod ("hashCode", kelas baru [0]); kembali; } catch (nosuchmethodException localNoSuchMethodeException) {lempar nosuchmethoderror baru (localnoSuchmethodeException.getMessage ()); } catch (ClassNotFoundException LocalClassNotFoundException) {Throw NoClassDeffoundError baru (LocalClassNotFoundException.getMessage ()); }}Akhirnya melihat bagian tentang Invoke:
public final void createOrder () {coba {this.h.invoke (this, m3, null); kembali; } catch (error | runimeException localError) {throw localError; } Catch (Throwable LocalThrowable) {lempar New UndeclaredthrowableException (Localthrowable); }}Faktanya, kelas proxy dinamis mewarisi dari proxy dan mengimplementasikan antarmuka yang diwarisi oleh kelas target. Metode Invoke disebut dalam metode CreateDer, yang mengimplementasikan implantasi logika sectional. Di sini kami juga menjawab pertanyaan, mengapa kelas target dari proxy dinamis JDK harus mengimplementasikan antarmuka, karena kelas proxy sebenarnya ditujukan pada proxy antarmuka, bukan kelas. Kelas proxy dinamis mewarisi dirinya dari proxy, dan Java tidak mengizinkan beberapa warisan. Kelas proxy dinamis dan kelas target masing -masing mengimplementasikan antarmuka. Kelas proxy mewujudkan panggilan ke metode kelas target melalui InvocationHandler.invoke.
Proxy Dinamis CGlib
Proxy CGLIB menggunakan kerangka pemrosesan bytecode ASM untuk mengonversi bytecode dan menghasilkan kelas baru, dan menggunakan metode penyadapan metode dalam subkelas untuk mencegat semua metode kelas induk untuk mengimplementasikan logika silang, yang lebih efisien daripada proxy dinamis JDK menggunakan teknologi refleksi. Namun, karena prinsip CGLIB adalah untuk secara dinamis menghasilkan kelas proxy subclass untuk kelas target, itu tidak dapat diproksi untuk metode yang dinyatakan sebagai final. Penggunaannya terutama melibatkan dua kategori:
Antarmuka MethodInterceptor: Antarmuka ini menyediakan Method intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) terutama digunakan untuk mencegat panggilan metode kelas target.
Objek arg0,: kelas target yang sedang diproksi
Metode arg1, metode delegasi
Objek [] arg2, parameter metode
MethodProxy Arg3: MethodProxy Object of Proxy Method
Kelas Penambah: Digunakan untuk membuat kelas proxy
Contoh:
Menerapkan antarmuka MethodInterceptor. Ketika kelas proxy memanggil metode, CGLIB akan memanggil kembali metode intersepsi antarmuka MethodInterceptor, sehingga menenun logika permukaan.
Paket com.sl.aop; impor java.lang.reflect.method; impor org.springframework.cglib.proxy.enhancer; Impor CLASSPRAMEWORK.CGLIB.PROXY.METHODECTOR; MethodInterceptor {Private Object TargetClass; Orderlogger Private Logger; CGLIBSERVICEPROXY PUBLIK (Object TargetClass, OrderLogger OrderLogger) {this.targetClass = TargetClass; this.orderlogger = orderlogger; } / *** Buat objek proxy** / objek publik getInstance () {Enhancer Enhancer = new Enhancer (); // atur kelas target (kelas yang perlu diproksikan) penambah.setsuperclass (this.targetClass.getClass ()); // Callback Method Enhancer.setCallback (ini); // buat objek proxy return exhance.create (); } / *** mencegat semua metode kelas target** / @Override Public Object Intercept (objek arg0, metode arg1, objek [] arg2, methodproxy arg3) melempar lempar {orderlogger.beforecreateOrder (); Objek o1 = arg3.invokeSuper (arg0, arg2); orderlogger.afterCreateOrder (); mengembalikan O1; }}Metode Uji:
public void testdynamicproxy () {system.setProperty (debuggingclasswriter.debug_location_property, "d: // class"); Layanan PesanServiceImpl = New OrderServiceImpl (); OrderLogger Logger = New OrderLogger (); Proxy cglibserviceproxy = cglibserviceproxy baru (serviceImpl, logger); // Buat kelas proxy dengan menghasilkan subclasses OrderServiceImpl proxyimp = (orderserviceImpl) proxy.getInstance (); proxyimp.createOrder (); }hasil:
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D://class"); Output kelas proxy dinamis CGLIB ke direktori yang ditentukan, mendekompilasi dan memeriksa wajah sebenarnya dari kelas proxy:
Paket com.sl.aop; impor com.sl.aop.orderServiceImpl; impor java.lang.reflect.method; impor org.springframework.cglib.core.reflectutils; impor org.spramework.cglibleT.core.sgnature; impor.springpring. org.springframework.cglib.proxy.factory; impor org.springframework.cglib.proxy.methodinterceptor; impor org.springframework.cglib.proxy.methodproxy; PUBLIC CLASSERVICEIMPL $$ peningkatan $$ $$ $ PREFACLEAGICY {PRECERSERFICHICEMICLEMPL PRICERSVICLEIMPL $$ UNDERBIBLIB {PREFOCLIBRICE. Cglib $ terikat; Objek statis publik Cglib $ factory_data; thread final private static cglib $ thread_callbacks; Private Static Final Callback [] CGLIB $ static_callbacks; Private MethodInterceptor CGLIB $ callback_0; objek statis pribadi cglib $ callback_filter; metode final statis pribadi cglib $ createorder $ 0 $ metode; Metode final statis pribadi proxy cglib $ createorder $ 0 $ proxy; objek akhir statis pribadi [] CGLIB $ emplicleArgs; metode final statis pribadi cglib $ sama dengan $ 1 $ metode; METODE METODE FINAL PRIBADI CGLIB $ Equals $ 1 $ Proxy; metode final statis pribadi cglib $ tostring $ 2 $ metode; METODE METODE Final STATIC PRIBADI CGLIB $ TOSTRING $ 2 $ Proxy; metode final statis pribadi cglib $ hashcode $ 3 $ metode; METODE METODE Final STATIC PRIBADI CGLIB $ HASHCODE $ 3 $ Proxy; Metode final statis privatcglib $ clone $ 4 $ metode; METODE FINAL STATIC PRIBADI CGLIB $ Klon $ 4 $ Proxy; static void cglib $ statichook1 () {cglib $ thread_callbacks = new threadLocal (); CGLIB $ emplementArgs = objek baru [0]; Kelas var0 = class.forname ("com.sl.aop.orderServiceImpl $$ Enhancerbycglib $$ 17779aa4"); Kelas var1; Metode [] var10000 = reflectutils.findmethods (string baru [] {"sama", "(ljava/lang/objek;) z", "tostring", "() ljava/lang/string;", "hashcode", "() i", "klon", "() () ljava/langa/langa/langa/lang/lang/lang/lang/lang/lang/lang/lang/lang/lang/lang/lang/lang/lang () Class.forname ("java.lang.object")). GetDeclaredMethods ()); CGLIB $ sama dengan $ 1 $ Method = var10000 [0]; CGLIB $ sama dengan $ 1 $ proxy = MethodProxy.Create (var1, var0, "(ljava/lang/objek;) z", "sama", "cglib $ sama dengan $ 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/objek;", "clone", "cglib $ clone $ 4"); Cglib $ createorder $ 0 $ method = reflectutils.findmethods (string baru [] {"createorder", "() v"}, (var1 = class.forname ("com.sl.aop.orderServiceImpl")). GetDeclaredMethods ()) [0]; Cglib $ createorder $ 0 $ proxy = MethodProxy.Create (var1, var0, "() v", "createOder", "cglib $ createDerer $ 0"); } final void cglib $ createOder $ 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! = null) {var10000.Intercept (ini, cglib $ createorder $ 0 $ Metode, cglib $ emplemsArgs, cglib $ createorder $ 0 $ proxy); } else {super.CreateOrder (); }} final boolean cglib $ sama $ 1 (objek var1) {return super.equals (var1); } public final boolean sama (objek var1) {MethodInterceptor var10000 = this.cglib $ callback_0; if (this.cglib $ callback_0 == null) {cglib $ bind_callbacks (this); var10000 = this.cglib $ callback_0; } if (var10000! = null) {objek var2 = var10000.intercept (ini, cglib $ sama $ 1 $ Metode, objek baru [] {var1}, cglib $ sama dengan $ 1 $ proxy); return var2 == null? false: ((boolean) var2) .booleanValue (); } else {return super.equals (var1); }} string terakhir 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 (ini, cglib $ tostring $ 2 $ Metode, cglib $ emplicArgs, cglib $ tostring $ 2 $ proxy): super.toString (); } final 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) {objek var1 = var10000.intercept (ini, cglib $ hashCode $ 3 $ METODE, CGLIB $ emplosdArgs, cglib $ hashCode $ 3 $ proxy); return var1 == null? 0: ((bilangan) var1) .IntValue (); } else {return super.hashCode (); }} objek akhir cglib $ clone $ 4 () melempar clonenotsupportedException {return super.clone (); } clone objek akhir yang dilindungi () melempar 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 (ini, cglib $ clone $ 4 $ METODE, CGLIB $ emplemsArgs, 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 $ createDer $ 0 $ proxy; } merusak; case -508378822: if (var10000.equals ("clone () ljava/lang/objek;")) {return cglib $ clone $ 4 $ proxy; } merusak; kasus 1826985398: if (var10000.equals ("sama (ljava/lang/objek;) z")) {return cglib $ sama $ 1 $ proxy; } merusak; Kasus 1913648695: if (var10000.equals ("tostring () ljava/lang/string;"))) {return cglib $ tostring $ 2 $ proxy; } merusak; kasus 1984935277: if (var10000.equals ("hashcode () i")) {return cglib $ hashcode $ 3 $ proxy; }} return null; } public orderServiceImpl $$ Enhancerbycglib $$ 17779AA4 () {CGLIB $ Bind_Callbacks (ini); } 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 static final void cglib $ bind_callbacks (objek var0) {orderserviceImpl $$ Enhancerbycglib $$ 17779aa4 var1 = (orderserviceImpl $$ Enhancerbycglib $$ 17779AA4) var0; if (! var1.cglib $ terikat) {var1.cglib $ bound = true; Objek 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]; }} objek publik newInstance (callback [] var1) {cglib $ set_thread_callbacks (var1); ORDERSERVICEIMPL $$ EnhancerbyCglib $$ 17779AA4 VAR10000 = New OrderServiceImpl $$ Enhancerbycglib $$ 17779AA4 (); Cglib $ set_thread_callbacks ((callback []) null); mengembalikan var10000; } objek publik newInstance (callback var1) {cglib $ set_thread_callbacks (callback baru [] {var1}); ORDERSERVICEIMPL $$ EnhancerbyCglib $$ 17779AA4 VAR10000 = New OrderServiceImpl $$ Enhancerbycglib $$ 17779AA4 (); Cglib $ set_thread_callbacks ((callback []) null); mengembalikan var10000; } objek publik newInstance (class [] var1, objek [] var2, callback [] var3) {cglib $ set_thread_callbacks (var3); PESENTERSERVICEIMPL $$ EnhancerbyCglib $$ 17779AA4 VAR10000 = New OrderServiceImpl $$ Enhancerbycglib $$ 17779AA4; switch (var1.length) {case 0: var10000. <inin> (); Cglib $ set_thread_callbacks ((callback []) null); mengembalikan var10000; Default: Lempar IllegalArgumentException baru ("Konstruktor tidak ditemukan"); }} callback publik getCallback (int var1) {cglib $ bind_callbacks (this); MethodInterceptor VAR10000; switch (var1) {case 0: var10000 = this.cglib $ callback_0; merusak; default: var10000 = null; } return var10000; } public void setCallback (int var1, callback var2) {switch (var1) {case 0: this.cglib $ callback_0 = (MethodInterceptor) var2; default:}} callback publik [] getCallbacks () {cglib $ bind_callbacks (this); return new callback [] {this.cglib $ callback_0}; } public void setCallbacks (callback [] var1) {this.cglib $ callback_0 = (MethodInterceptor) var1 [0]; } static {cglib $ statichook1 (); }}Dalam kode di atas, Anda dapat melihat bahwa kelas proxy OrderServiceImpl $$ Enhancerbycglib $$ 17779AA4 mewarisi target kelas pesanan layanan dan mengimplementasikan pabrik antarmuka. Di kelas proxy, dua metode cglib $ createDerD $ 0 dan createDeroDer dihasilkan:
Metode CGLIB $ CreateOder $ 0 secara langsung memanggil supper.createOrder
Metode CreateOrder pertama -tama menghitung apakah panggilan balik dari antarmuka MethodInterceptor diimplementasikan. Jika ada, metode intersep antarmuka MethodInterceptor dipanggil. Menurut implementasi sebelumnya, panggilan ke metode target diimplementasikan. Object o1 = arg3.invokeSuper(arg0, arg2) diimplementasikan. InvokeSuper sebenarnya adalah metode CGLIB$createOrder$0() dari kelas proxy yang secara langsung dipanggil, dan kelas target CreateDerder akhirnya dipanggil.
Perbandingan dua agen
JDK Dynamic Proxy:
Kelas proxy dan kelas delegasi mengimplementasikan antarmuka yang sama. Ini terutama mengimplementasikan AvocationHandler melalui kelas proxy dan menulis ulang metode Invoke untuk melakukan proxy dinamis. Metode ini akan ditingkatkan dalam metode Invoke. Keuntungan dari metode ini: tidak ada antarmuka yang dikodekan dengan keras, dan tingkat penggunaan kembali kode tinggi. Kekurangan: Hanya kelas delegasi yang dapat diimplementasikan oleh antarmuka
Proxy Dinamis CGlib:
Kelas proxy mengambil kelas delegasi sebagai kelas induknya dan membuat dua metode untuk metode delegasi non-final di dalamnya. Salah satunya adalah metode yang sama dengan tanda tangan metode delegasi, yang akan memanggil metode delegasi melalui super dalam metode; Yang lainnya adalah metode yang unik untuk kelas proxy. Dalam metode proxy, itu akan menentukan apakah ada objek yang mengimplementasikan antarmuka MethodInterceptor. Jika ada, metode intersep akan dipanggil untuk proxy metode delegasi. Keuntungan: Ini dapat meningkatkan pengoperasian kelas atau antarmuka saat runtime, dan kelas delegasi tidak perlu mengimplementasikan antarmuka. Kekurangan: Ini tidak dapat memproksi kelas akhir dan metode akhir.
Meringkaskan
Di atas adalah seluruh konten artikel ini. Saya berharap konten artikel ini memiliki nilai referensi tertentu untuk studi atau pekerjaan semua orang. Jika Anda memiliki pertanyaan, Anda dapat meninggalkan pesan untuk berkomunikasi. Terima kasih atas dukungan Anda ke wulin.com.