Halo semuanya!
Nah, sebelum Tahun Baru dan dimulainya aliran kesepuluh,
"Pengembang Java" benar-benar bercanda. Jadi kami memiliki satu pelajaran terbuka yang kami siapkan untuk publikasi dan artikel hari ini, dari mana Anda akan belajar tentang proxy Java dinamis: apa itu, kapan dan bagaimana menggunakannya dalam kode.
Apa itu proxy?Proxy adalah pola desain. Kami membuat dan menggunakannya untuk menambah dan mengubah fungsionalitas kelas yang ada. Dalam hal ini, objek proxy digunakan bukan yang asli. Biasanya ia menggunakan metode yang sama seperti yang asli, dan di kelas proxy Java memperpanjang yang asli. Proxy dapat memanggil metode pada objek sumber karena memiliki deskriptor asli.
Dengan demikian, kelas proksi dengan mudah mengimplementasikan banyak hal:
- mencatat awal dan berhenti dari metode;
- pemeriksaan argumen tambahan;
- meniru perilaku kelas sumber;
- implementasi inisialisasi ditangguhkan dari sumber daya mahal;

Semua ini terjadi tanpa mengubah kode kelas asli. Daftar lengkap tidak terbatas pada contoh di atas, mereka hanya sebagian kecil saja.
Dalam praktiknya, kelas proksi tidak secara langsung mengimplementasikan fungsi tersebut. Mengikuti prinsip tanggung jawab tunggal, kelas proxy secara langsung hanya melakukan proxy, dan perubahan perilaku diterapkan pada penangan. Saat memanggil objek proxy alih-alih yang asli, proxy memutuskan apakah akan memanggil metode asli atau beberapa penangan. Pawang dapat melakukan tugasnya sendiri dan merujuk ke metode asli.
Meskipun pola proxy tidak hanya digunakan untuk membuat objek proxy dan kelas di runtime, di Jawa ini adalah topik yang sangat menarik. Dalam artikel ini, saya fokus pada proxy semacam itu.
Ini adalah topik kompleks yang memerlukan penggunaan kelas refleksi, atau memanipulasi bytecode, atau mengkompilasi kode Java yang dihasilkan secara dinamis. Atau mungkin sekaligus. Untuk mencegah kelas baru dari tersedia sebagai bytecode saat runtime, bytecode dan classloader yang dihasilkan akan diperlukan untuk memuat bytecode. Untuk membuat bytecode, gunakan
cglib ,
bytebuddy, atau kompiler Java
bawaan .
Pentingnya pemisahan tanggung jawab, dalam kasus kami, menjadi jelas, Anda hanya perlu memikirkan kelas proxy dan penangan yang mereka panggil. Kelas proxy dihasilkan saat runtime, tetapi penangan yang dipanggil dapat ditambahkan ke kode sumber reguler dan dikompilasi dengan program lainnya.
Bagaimana cara menggunakannya dalam kode kita?
Paling sederhana adalah dengan menggunakan
java.lang.reflect.Proxy
, yang merupakan bagian dari JDK. Kelas ini dapat membuat kelas proxy atau turunannya secara langsung. Menggunakan proxy yang dibangun ke Jawa sangat sederhana. Yang perlu Anda lakukan adalah mengimplementasikan
java.lang.InvocationHandler
sehingga objek proxy dapat memanggilnya. Antarmuka
InvocationHandler
sangat sederhana dan hanya berisi satu metode:
invoke()
. Ketika dipanggil, argumen berisi objek asli yang diproksi, metode yang dipanggil (sebagai refleksi dari objek
Method
) dan array objek dari argumen asli. Cuplikan kode di bawah ini menunjukkan aplikasi:
package proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class JdkProxyDemo { interface If { void originalMethod(String s); } static class Original implements If { public void originalMethod(String s) { System.out.println(s); } } static class Handler implements InvocationHandler { private final If original; public Handler(If original) { this.original = original; } public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { System.out.println("BEFORE"); method.invoke(original, args); System.out.println("AFTER"); return null; } } public static void main(String[] args){ Original original = new Original(); Handler handler = new Handler(original); If f = (If) Proxy.newProxyInstance(If.class.getClassLoader(), new Class[] { If.class }, handler); f.originalMethod("Hallo"); } }
Untuk memanggil metode asli dari objek sumber, pawang perlu akses ke sana. Apa yang tidak disediakan oleh implementasi proxy Java. Anda harus meneruskan argumen sendiri ke instance handler dalam kode. (Perhatikan objek (biasanya disebut proxy), yang diteruskan sebagai argumen ke penangan yang disebut. Ini adalah objek proxy yang dihasilkan Jawa secara dinamis, dan bukan objek yang ingin kami proksi.) Dengan demikian, Anda dapat menggunakan sebagai terpisah objek handler untuk setiap kelas sumber, serta objek umum yang tahu cara memanggil objek asli, jika ada metode untuk ini sama sekali.
Dalam kasus khusus, Anda dapat membuat penangan panggilan dan antarmuka proxy tanpa objek asli. Selain itu, kelas untuk mengimplementasikan antarmuka dalam kode sumber tidak diperlukan. Ini diimplementasikan oleh kelas proxy yang dibuat secara dinamis.
Jika kelas proksi tidak mengimplementasikan antarmuka, Anda harus mempertimbangkan untuk menggunakan beberapa implementasi proxy lainnya.
AKHIR
Menunggu komentar dan pertanyaan Anda. Seperti biasa, baik di sini, atau Anda dapat pergi ke
Vitaly untuk
hari yang terbuka .