Artikel ini adalah tentang masalah yang sulit di Java. Dengan menggunakan pustaka inti Java untuk mengimplementasikan metode AOP sederhana dan menganalisis dan membandingkan kode instan. Berikut ini adalah semua konten:
Spring adalah kerangka kerja open source yang sangat populer, dan AOP (pemrograman sectional) adalah salah satu konsep paling penting dari musim semi. Untuk lebih memahami dan mempelajari ide -ide AOP, menggunakan perpustakaan inti untuk mencapainya sekaligus adalah cara yang baik.
Pertama, mari kita perkenalkan konsep AOP. AOP (pemrograman berorientasi aspek), yaitu, pemrograman berorientasi tangensial. Yang disebut pemrograman berorientasi tangensial adalah gagasan merancang kode dari perspektif area cross-sectional. Gagasan OOP tradisional adalah menggunakan warisan enkapsulasi dan polimorfisme untuk membangun hubungan hierarkis vertikal, tetapi tidak cocok untuk mendefinisikan hubungan horizontal. Ide AOP memberikan suplemen yang baik untuk ini.
Misalnya, kode manajemen log sering tersebar secara horizontal di banyak tingkat objek, tetapi tidak ada hubungannya dengan fungsi inti dari objek yang sesuai. Ada juga banyak kode serupa, seperti verifikasi izin, output debug, pemrosesan transaksi, dll., Yang juga sama. Ini tidak kondusif untuk penggunaan kembali dan manajemen kode.
Pada saat ini, teknologi AOP muncul. Ia menggunakan teknologi "crosscutting" untuk menembus jauh ke dalam objek enkapsulasi, merangkum perilaku umum yang mempengaruhi beberapa kelas ke dalam modul yang dapat digunakan kembali, dan menamainya "aspek", yaitu pengiris. "Bagian" yang disebut hanya dienkapsulasi oleh logika atau tanggung jawab yang tidak terkait dengan bisnis tetapi disebut bersama oleh modul bisnis, yang nyaman untuk mengurangi kode duplikat sistem, mengurangi kopling antara modul, dan kondusif menjadi operasi dan pemeliharaan berikutnya.
Jadi bagaimana AOP diimplementasikan?
Jawabannya adalah proxy dinamis (akan ada bab lain di proxy untuk detailnya, jadi saya tidak akan membahas detail di sini). Ada dua cara untuk mengimplementasikan proxy dinamis, satu adalah proxy dinamis JDK, dan yang lainnya adalah proxy dinamis CGLIB.
Kemudian gunakan dua metode untuk membuat kastanye sederhana.
Mari kita rancang skenario terlebih dahulu, misalkan kita memiliki antarmuka komputasi icalculator dan kalkulator kalkulator yang mengimplementasikan antarmuka ini.
antarmuka publik icalculator {// Operasi tambahan int tambahan publik (int a, int b); // pengurangan int intractract publik (int a, int b); // Beberapa int Multiply publik (int a, int b); // Dividasi Int Public Define (int a, int b);} CalculatorImpl kelas publik mengimplementasikan icalCulator {@Override public int add (int a, int b) {return a + b; } @Override Public int kurangi (int a, int b) {return a - b; } @Override Public int Multiply (int a, int b) {return a * b; } @Override public int define (int a, int b) {return a / b; }}Bagaimana cara merekam jumlah total kali metode kalkulator digunakan tanpa mengubah kode internal kelas kalkulator asli?
Dengan proxy dinamis, sebenarnya sangat sederhana. Pertama -tama buat kelas dan implementasikan antarmuka InvocationHandler, timpa metode Invoke.
TestHandler kelas publik mengimplementasikan InvocationHandler {private objek TargetObject; Private Int Usetimes; // ikat objek delegasi dan kembalikan bik objek publik kelas proxy (objek targetObject) {this.targetObject = targetObject; return proxy.newproxyInstance (targetObject.getClass (). getClassLoader (), targetObject.getClass (). getInterfaces (), this); } @Override Public Object Invoke (objek proxy, metode metode, objek [] args) melempar lempar {// lakukan sesuatu sebelum (); Hasil Objek = Method.Invoke (TargetObject, args); setelah(); hasil pengembalian; } private void sebelum () {System.out.println ("Kita dapat melakukan sesuatu sebelum menghitung."); } private void after () {Usetimes ++; System.out.println ("Digunakan:"+Usetimes+"Times"); }}Meskipun tampaknya ada terlalu banyak kode, metode utama adalah metode Invoke. Hasil objek = metode.invoke (targetObject, args); Ini setara dengan terus menggunakan parameter asli untuk menjalankan metode asli. Sebelum dan sesudahnya di sini adalah fungsi yang disesuaikan, yang dapat melakukan beberapa hal yang ingin kami lakukan sebelum dan sesudah kode objek dieksekusi, seperti jumlah penggunaan di sini.
Dalam metode BIND, objek proxy target dilewatkan dan instance kelas proxy dikembalikan. Selanjutnya, mari kita lihat cara menggunakan:
TestProxy kelas publik {public static void main (string [] args) {testHandler proxy = new testHandler (); Icalculator Calculate = (icalculator) proxy.bind (calculatorImpl baru ()); int result = calculate.add (1,2); System.out.println ("Hasilnya adalah:"+hasil); Hasil = Hitung.subtract (3,2); System.out.println ("Hasilnya adalah:"+hasil); hasil = kalkulater.multiply (4,6); System.out.println ("Hasilnya adalah:"+hasil); hasil = kalkulater.devide (6,2); System.out.println ("Hasilnya adalah:"+hasil); }}Kami pertama -tama mendefinisikan testhandler, dan kemudian mendapatkan instance proxy melalui metode BIND, dan kemudian kami dapat menggunakan instance ini secara langsung. Hasil operasi adalah sebagai berikut:
kita bisa melakukan sesuatu sebelum menghitung. Digunakan: 1 Hasilnya adalah: 3 kita dapat melakukan sesuatu sebelum menghitung. Digunakan: 2 Hasilnya adalah: 1Kami dapat melakukan sesuatu sebelum menghitung. Digunakan: 3 Hasilnya adalah: 24 Kami dapat melakukan sesuatu sebelum menghitung. Digunakan: 4 Hasilnya adalah: 3
Dengan cara ini, kami mengimplementasikan ekstensi kode tanpa memodifikasi kode internal CalculatorImpl.
Selanjutnya, gunakan CGLIB untuk mengimplementasikannya sekali.
Pertama -tama buat kelas untuk mengimplementasikan antarmuka MethodInterceptor dan mengganti metode intersep. Kode lain mirip dengan menggunakan proxy JDK, tetapi proses mendapatkan objek proxy berbeda.
kelas publik CGlibproxy mengimplementasikan MethodInterceptor {private int eSetimes; target objek pribadi; objek publik getInstance (objek target) {this.target = target; Penambah penambah = penambah baru (); Enhancer.setsuperclass (this.target.getClass ()); Enhancer.setCallback (ini); return enhancer.create (); } @Override Public Object Intercept (Object O, Metode Metode, Objek [] Objek, MethodProxy MethodProxy) melempar Throwable {sebelum (); Hasil Objek = MethodProxy.invokeSuper (O, Objek); setelah(); hasil pengembalian; } private void sebelum () {System.out.println ("Kita dapat melakukan sesuatu sebelum menghitung."); } private void after () {Usetimes ++; System.out.println ("Digunakan:"+Usetimes+"Times"); }}Ujilah:
testcglibproxy kelas publik {public static void main (string [] args) {cglibproxy cglibproxy = new cglibproxy (); Icalculator calculate = (icalculator) cglibproxy.getInstance (calculatorImpl baru ()); int result = calculate.add (1,2); System.out.println ("Hasilnya adalah:"+hasil); Hasil = Hitung.subtract (3,2); System.out.println ("Hasilnya adalah:"+hasil); Hasil = Hitung.Multiply (4,6); System.out.println ("Hasilnya adalah:"+hasil); Hasil = Hitung.Devide (6,2); System.out.println ("Hasilnya adalah:"+hasil); }}Hasil operasi adalah sebagai berikut:
kita bisa melakukan sesuatu sebelum menghitung. Digunakan: 1 Hasilnya adalah: 3 kita dapat melakukan sesuatu sebelum menghitung. Digunakan: 2 Hasilnya adalah: 1Kami dapat melakukan sesuatu sebelum menghitung. Digunakan: 3 Hasilnya adalah: 24 Kami dapat melakukan sesuatu sebelum menghitung. Digunakan: 4 Hasilnya adalah: 3
Sekarang kami mendapatkan hasil yang sama. (Dua paket diperlukan, CGLIB-2.2.2.jar ASM-3.3.Jar)
Kedua metode memiliki kekuatan sendiri. JDK Proxy perlu mengatur antarmuka sebelum mengimplementasikan proxy. Ini adalah kerugian dan keuntungannya. Kerugiannya adalah bahwa ini akan sedikit lebih merepotkan, dan itu tidak dapat memproksi yang sudah dienkapsulasi dan tidak mengimplementasikan antarmuka. Metode proxy CGLIB tidak memerlukan penggunaan antarmuka. Tetapi juga karena inilah proxy JDK hanya mencegat metode yang menimpa antarmuka di kelas, sementara CGLIB mencegat semua panggilan metode kelas. Keduanya memiliki pro dan kontra mereka, sehingga keadaan spesifik perlu dianalisis. Di musim semi, dua mode proxy digunakan campuran.