Kelas proxy dinamis Java dapat dibagi menjadi dua jenis.
Proxy Static: Dibuat oleh programmer atau secara otomatis menghasilkan kode sumber dengan alat tertentu dan mengkompilasinya. Sebelum program berjalan, file .class dari kelas proxy sudah ada.
Dinamis Proxy: Diciptakan secara dinamis menggunakan mekanisme refleksi saat program berjalan.
1. Pertama, kami akan mendemonstrasikan proxy dinamis Java.
Sekarang kami memiliki antarmuka bisnis yang sederhana, sebagai berikut:
Salinan kode adalah sebagai berikut:
paket testaop;
antarmuka publik mengatakan {
public void wayshello (nama string);
public void berbicara (nama string);
}
Kelas implementasi sederhana yang mengatakan IMPL, sebagai berikut:
Salinan kode adalah sebagai berikut:
paket testaop;
kelas publik mengatakan implements yang mengatakan {
@Mengesampingkan
public void sayshello (nama string) {
// TODO Stub Metode yang Dihasilkan Otomatis
System.out.println (name + ": halo semuanya!");
}
@Mengesampingkan
public void berbicara (nama string) {
// TODO Stub Metode yang Dihasilkan Otomatis
System.out.println (Nama + ": Maksud saya, kita harus bekerja keras untuk membangun masyarakat yang harmonis!");
}
}
Apa yang ingin kita capai adalah secara dinamis menanamkan pemrosesan sebelum dan sesudah mengatakan Hello dan berbicara.
JDK Dynamic Proxy terutama menggunakan dua kelas dalam paket java.lang.reflect: Proxy dan InvocationHandler.
InvocationHandler adalah antarmuka yang mendefinisikan logika silang dengan mengimplementasikan antarmuka ini dan memanggil kode kelas target melalui mekanisme refleksi, secara dinamis menjalin logika silang dan logika bisnis bersama-sama.
Proxy menggunakan InvocationHandler untuk secara dinamis membuat instance yang sesuai dengan antarmuka tertentu dan menghasilkan objek proxy dari kelas target.
Sebagai berikut, kami membuat instance InvocationHandler:
Salinan kode adalah sebagai berikut:
paket testaop;
impor java.lang.reflect.invocationHandler;
impor java.lang.reflect.method;
Kelas publik MyInvocationHandler mengimplementasikan InvocationHandler {
target objek pribadi;
MyInvocationHandler (Target Objek) {
this.target = target;
}
@Mengesampingkan
Invoke Objek Publik (Proksi Objek, Metode Metode, Objek [] args)
melempar lempar {
// Jalankan sebelum metode target
System.out.println ("―6666666666 A ~ ―6 ―6 kata" - - - - - - - - - - ");
System.out.println ("Silakan berbicara di panggung orang berikutnya!");
// Panggilan metode target
Objek obj = metode.invoke (target, args);
// Jalankan metode target setelahnya
System.out.println ("Semua orang tepuk tangan dan dorongan!");
kembalikan obj;
}
}
Ini tesnya:
Salinan kode adalah sebagai berikut:
paket testaop;
impor java.lang.reflect.proxy;
Kelas Publik JDKProxyTest {
public static void main (string [] args) {
// Kategori bisnis target yang ingin Anda butuhkan
Mengatakan target = kata baru ();
// Tenunkan kelas target dan kelas lintas-potong bersama-sama
MyInvocationHandler handler = myInvocationHandler baru (target);
// Buat instance proxy
Mengatakan proxy = (mengatakan) proxy.newproxyInstance (
target.getClass (). getClassLoader (), // class loader dari kelas target
target.getClass (). getInterfaces (), // antarmuka kelas target
Handler); // Kelas Cross-Cut
proxy.sayhello ("Xiao Ming");
proxy.talking ("xiaoli");
}
}
Operasi adalah sebagai berikut:
Salinan kode adalah sebagai berikut:
―6666666666 ACAT
Tolong bicaralah di atas panggung orang berikutnya!
Xiao Ming: Halo semuanya!
Semua orang bertepuk tangan dan didorong!
―6666666666 ACAT
Tolong bicaralah di atas panggung orang berikutnya!
Xiaoli: Maksud saya, kita harus bekerja keras untuk membangun masyarakat yang harmonis!
Semua orang bertepuk tangan dan didorong!
Ada batasan besar untuk menggunakan proxy dinamis JDK, yaitu bahwa ia mensyaratkan bahwa kelas target harus mengimplementasikan antarmuka metode yang sesuai, dan hanya dapat membuat instance proxy untuk antarmuka. Kita dapat melihat dalam metode proxy newProxyInstance di kelas uji di atas bahwa parameter kedua dari metode ini adalah antarmuka kelas target. Jika kelas ini tidak menerapkan antarmuka, itu tergantung pada proxy dinamis CGLIB.
CGLIB mengadopsi teknologi bytecode yang sangat mendasar, yang dapat membuat subkelas untuk kelas, dan menggunakan metode mencegat teknik dalam subkelas untuk mencegat semua panggilan metode kelas induk, dan menanamkan logika lintas-pemotongan dalam situasi.
2. Selanjutnya, kami akan mendemonstrasikan proxy dinamis CGLIB.
Pertama-tama, kita perlu memandu paket.
Kami pertama -tama membuat proxy creator cglibproxy:
Salinan kode adalah sebagai berikut:
paket testaop.cglib;
impor java.lang.reflect.method;
impor net.sf.cglib.proxy.enhancer;
impor net.sf.cglib.proxy.methodInterceptor;
impor net.sf.cglib.proxy.methodproxy;
CGLIBPROXY kelas publik mengimplementasikan MethodInterceptor {
Penambah penambah = penambah baru ();
objek publik getProxy (kelas clazz) {
// atur subkelas yang akan dibuat
peningkatan.setsuperclass (clazz);
Enhancer.setCallback (ini);
// secara dinamis membuat instance subkelas melalui teknologi bytecode
return enhancer.create ();
}
@Mengesampingkan
Intercept Objek Publik (objek OBJ, metode metode, objek [] args,
MethodProxy Proxy) melempar {
// TODO Stub Metode yang Dihasilkan Otomatis
System.out.println ("―6666666666 A ~ ―6 ―6 kata" - - - - - - - - - - ");
System.out.println ("Silakan berbicara di panggung orang berikutnya!");
// Panggilan metode target
Hasil objek = proxy.invokesuper (obj, args);
// Jalankan metode target setelahnya
System.out.println ("Semua orang tepuk tangan dan dorongan!");
hasil pengembalian;
}
}
Kemudian tes:
Salinan kode adalah sebagai berikut:
paket testaop.cglib;
impor testaop.
impor testaop.sayingImpl;
CGLIBPROXYTEST kelas publik {
public static void main (string [] args) {
Proxy cglibproxy = cglibproxy baru ();
// Buat kelas proxy dengan menghasilkan subclass secara dinamis
Mengatakan target = (mengatakan) proxy.getproxy (mengatakanMpl.class);
target.sayhello ("Xiao Ming");
target.talking ("xiaoli");
}
}
Hasilnya tidak berbeda dengan proxy dinamis JDK.
Baik proxy dinamis JDK dan proxy dinamis CGLIB adalah peningkatan runtime, yang ditingkatkan dengan menanamkan kode lintas-potong ke dalam kelas proxy. Tidak seperti ini, AspectJ, yang dapat menanamkan kode silang dalam periode kompilasi melalui kompiler khusus.