memperkenalkan
Seperti yang kita semua tahu, AOP (pemrograman berorientasi bagian) adalah salah satu fitur kerangka kerja musim semi. AOP memberikan skalabilitas yang sangat tinggi dengan menetapkan masalah pemotongan silang. Jadi bagaimana cara kerja AOP di musim semi? Ketika Anda hanya dapat menggunakan inti java tetapi membutuhkan teknologi AOP, jawaban untuk pertanyaan ini menjadi sangat kritis. Tidak hanya itu, dalam wawancara untuk posisi teknis canggih, pertanyaan seperti itu sering muncul sebagai pertanyaan tes. Lihat, teman saya baru -baru ini menghadiri wawancara dan ditanya pertanyaan yang sulit - bagaimana menerapkan AOP tanpa menggunakan perpustakaan musim semi dan terkait, dan hanya java inti. Oleh karena itu, saya akan memberikan garis besar dalam artikel ini untuk membantu Anda memahami cara menerapkan AOP menggunakan inti Java (tentu saja, AOP ini memiliki batasan fungsional tertentu). Perhatikan bahwa artikel ini bukan studi perbandingan Spring AOP dan Java AOP, tetapi tutorial tentang penerapan AOP dengan bantuan pola desain yang melekat di inti Java.
Saya percaya pembaca sudah tahu apa itu AOP dan bagaimana menggunakannya dalam kerangka musim semi, jadi artikel ini hanya berfokus pada cara mengimplementasikan AOP tanpa menggunakan Spring. Pertama -tama, kita harus tahu bahwa Spring menggunakan dua teknologi: JDK Proxy dan CGLIB untuk mengimplementasikan AOP. JDK Dynamic Proxy menyediakan cara yang fleksibel untuk mengaitkan metode dan melakukan operasi yang ditentukan, tetapi harus ada pembatasan saat melakukan operasi: antarmuka terkait dan kelas implementasi antarmuka harus disediakan terlebih dahulu. Berlatihlah untuk menciptakan pengetahuan sejati, mari kita pahami kalimat ini melalui suatu kasus! Sekarang ada program kalkulator untuk melakukan beberapa operasi matematika. Mari kita pertimbangkan fungsi divisi. Pertanyaannya saat ini adalah: jika kerangka kerja inti sudah memiliki kode untuk mengimplementasikan divisi, dapatkah kita membajaknya dan melakukan verifikasi tambahan ketika kode dieksekusi? Jawabannya adalah ya, dan saya akan membuktikan ini dengan cuplikan kode yang disediakan di bawah ini. Pertama, mari kita lihat kode antarmuka dasar:
Kalkulator Antarmuka Publik {Public Int Calculate (int a, int b);}Kode kelas implementasi antarmuka ini adalah sebagai berikut:
Kalkulator Public CalculatorImpl mengimplementasikan kalkulator {@Override int calculate int (int a, int b) {return a/b; }}Dengan asumsi bahwa kita tidak dapat memperbaiki kode di atas atau membuat perubahan pada perpustakaan inti, bagaimana kita dapat menerapkan fungsi verifikasi dengan sempurna? Mengapa tidak mencoba fungsi proxy dinamis JDK.
Kelas publik SomeHandler mengimplementasikan InvocationHandler {// kode dihilangkan untuk kesederhanaan ... .. @Override Objek publik Invoke (Proxy Objek, Metode Metode, Objek [] Params) melempar Throwable {// Validasi Bisnis Kompleks dan Hasil Objek Logika = Method.invoke (TargetObject, params); hasil pengembalian; }}Mari kita lihat bagaimana fungsi verifikasi yang diimplementasikan oleh JDK Dynamic Proxy bekerja melalui kelas uji.
public static void main (string [] args) {calculatorImpl calcImppl = calculatorImpl baru (); Kalkulator proxied = (kalkulator) proxyfactory.getproxy (calculator.class, calcImppl, new somewandler (calcImpl)); Hasil int = proksied.kalkulat (20, 10); System.out.println ("Hasil Akhir :::" + Hasil); }Dari hasilnya, kita dapat melihat bahwa dengan hanya menerapkan antarmuka Air InvocationHandler yang kuat, kita bisa mendapatkan implementasi pengait. Menurut dokumentasi JDK, antarmuka InvocationHandler menggunakan instance proxy untuk menangani panggilan metode.
Sekarang kita tahu bahwa metode Invoke () dari InvocationHandler dapat membantu kita menyelesaikan masalah. Jadi mari kita selesaikan masalah baru - bagaimana kita bisa melakukan operasi sebelum dan sesudah eksekusi metode? Singkatnya, dapatkah kita menghubungkan metode dengan menambahkan beberapa AOP (sebelum, setelah, sekitar) (Catatan Penerjemah: Teks asli ditambahkan beberapa AOP, tapi saya pikir Handler bertindak sebagai aspek)? Jawabannya juga ya. Ikuti langkah -langkah di bawah ini untuk membuat template kode ramping untuk memenuhi persyaratan ini:
Dua cara untuk mengimplementasikan AOP:
1. Implementasi proxy dinamis yang disediakan oleh JDK
antarmuka
Public Interface userbean {void getUser (); membatalkan adduser (); void updateUser (); void deleteUser (); } Kelas Implementasi Asli
kelas publik UserBeanImpl mengimplementasikan userbean {private string user = null; Public UserBeanImpl () {} UserBeanImpl publik (string user) {this.user = user; } string publik getUserName () {return user; } public void getUser () {System.out.println ("Ini getUser () metode!"); } public void setUser (string user) {this.user = user; System.out.println ("Ini adalah metode setuser ()!"); } public void addUser () {System.out.println ("This is AddUser () metode!"); } public void updateUser () {System.out.println ("Ini adalah updateUser () metode!"); } public void deleteUser () {System.out.println ("This is deleteUser () metode!"); }} Kelas Agen
impor java.lang.reflect.invocationHandler; impor java.lang.reflect.method; impor java.lang.reflect.proxy; impor com.cignacmc.finance.bean.userbeanImpl; Public Class UserBeanProxy mengimplementasikan InvocationHandler {Private Object TargetObject; Public UserBeanProxy (Object TargetObject) {this.targetObject = TargetObject; } Invoke Objek Publik (Proxy Objek, Metode Metode, Objek [] args) melempar Throwable {userBeanImpl userbean = (userbeanImpl) targetObject; String username = userbean.getUserName (); Hasil Objek = NULL; // penilaian izin jika (nama pengguna! = Null &&! " } hasil pengembalian; }}
Kelas tes
impor java.lang.reflect.proxy; impor com.cignacmc.finance.bean.userbean; impor com.cignacmc.finance.bean.userbeanImpl; impor com.cignacmc.finance.proxy.userbeanproxy; Public Class Proxyexe {public static void main (string [] args) {System.out.println ("terbukti ........."); UserBeanImpl targetObject = UserBeanImpl baru ("Bob Liang"); UserBeanProxy Proxy = UserBeanProxy baru (TargetObject); // Hasilkan objek objek proxy objek Ususbean = (userbean) proxy.newproxyInstance (targetObject.getClass (). GetClassLoader (), targetObject.getClass (). GetInterfaces (), proxy); Object.adduser (); System.out.println ("Tidak terbukti ............"); targetObject = UserBeanImpl baru (); proxy = UserBeanProxy baru (TargetObject); // Hasilkan objek objek proxy = (userbean) proxy.newproxyInstance (targetObject.getClass (). GetClassLoader (), targetObject.getClass (). GetInterfaces (), proxy); Object.adduser (); }}
Keluaran:
Terbukti ............ Ini adalah metode adduser ()! Tidak terbukti ..........
Dari contoh di atas, metode yang dipanggil addUser () dapat berhasil dicegat dan diproses sesuai.
2. Buat kelas proxy melalui cglib
Keuntungannya adalah bahwa objek target kami tidak memerlukan kelas primitif antarmuka untuk diimplementasikan.
kelas publik clientbean {private string name = null; clientBean publik () {} klien publik (nama string) {this.name = name; } public void addClient () {System.out.println ("Ini adalah metode addClient ()!"); } public void deleteClient () {System.out.println ("This is deleteClient () metode!"); } public void getClient () {System.out.println ("This is getClient () metode!"); } public void getClient () {System.out.println ("Ini getClient ()) metode!"); } public void updateClient () {System.out.println ("Ini adalah metode updateClient ()!"); } public string getClientName () {return name; } public void setClientName (name string) {this.name = name; }} Kelas Agen
impor java.lang.reflect.method; impor com.cignacmc.finance.bean.clientbean; impor net.sf.cglib.proxy.enhancer; impor net.sf.cglib.proxy.methodInterceptor; impor net.sf.cglib.proxy.methodInterceptor; impor net.sf.cglib.proxy.methodproxy; kelas publik cGlibproxy mengimplementasikan MethodInterceptor {Private Object TargetObject; objek publik createProxyObject (objek targetObject) {this.targetObject = targetObject; Penambah penambah = penambah baru (); Enhancer.setsuperclass (this.targetObject.getClass ()); Enhancer.setCallback (ini); return enhancer.create (); } Intercept Objek Publik (Proksi Objek, Metode Metode, Objek [] args, MethodProxy MethodProxy) Melemparkan Throwable {ClientBean ClientBean = (ClientBean) TargetObject; String username = clientBean.getClientName (); Hasil Objek = NULL; if (username! = null &&! "". Equals (username)) {result = method.invoke (targetObject, args); } hasil pengembalian; }} Kelas tes
impor java.lang.reflect.proxy; impor com.cignacmc.finance.bean.clientbean; impor com.cignacmc.finance.bean.userbean; impor com.cignacmc.finance.bean.userbeanImpl; impor com.cignacmc.finance.proxy.cglibproxy; impor com.cignacmc.finance.proxy.userbeanproxy; Proxyexe kelas publik {public static void main (string [] args) {System.out.println ("........ proxy cglib ............"); System.out.println ("terbukti ..............."); Cglibproxy cproxy = cglibproxy baru (); ClientBean ClientBean = (ClientBean) cProxy.createProxyObject (klien baru ("Bob Liang")); clientbean.addclient (); System.out.println ("Tidak terbukti ..............."); cproxy = cglibproxy baru (); clientBean = (clientBean) cProxy.createProxyObject (klien baru ()); clientbean.addclient (); }}
Keluaran:
..... proxy cglib .................. terbukti ............ ini adalah metode addClient ()! Tidak terbukti ............