Proksi Dinamis dengan InvocationHandler
Buat proksi dinamis JDK untuk mencegat pemanggilan metode interface demi pencatatan, caching, dan percobaan ulang.
Proksi Dinamis dengan InvocationHandler adalah pelajaran Java Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Java Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Java Academy mencakup 4 pelajaran total.
Apa Itu Proksi Dinamis?
Proksi dinamis JDK adalah objek yang dibuat saat program berjalan dan mengimplementasikan satu atau beberapa antarmuka. Semua pemanggilan metode diteruskan ke InvocationHandler yang Anda sediakan.
Membuat Proksi dengan Proxy.newProxyInstance
Panggil Proxy.newProxyInstance(classLoader, interfaces[], handler) untuk membuat proksi. Proksi tersebut mengimplementasikan semua antarmuka yang tercantum.
UserService proxy = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(),
new Class[]{UserService.class},
new LoggingHandler(realService)
);
proxy.findById(42L); // intercepted by LoggingHandlerAntarmuka InvocationHandler
Implementasikan InvocationHandler untuk menangani setiap pemanggilan metode. Penangan tersebut menerima objek proksi, metode yang dipanggil, dan argumennya.
public class LoggingHandler implements InvocationHandler {
private final Object target;
public LoggingHandler(Object target) { this.target = target; }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(">> " + method.getName());
Object result = method.invoke(target, args);
System.out.println("<< " + method.getName());
return result;
}
}Proksi untuk Penyimpanan Cache
InvocationHandler dapat menyimpan hasil dalam cache: jika cache berisi hasil untuk argumen tersebut, kembalikan hasilnya; jika tidak, panggil metode sebenarnya dan simpan hasilnya.
public class CachingHandler implements InvocationHandler {
private final Object target;
private final Map<String, Object> cache = new HashMap<>();
public CachingHandler(Object target) { this.target = target; }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String key = method.getName() + Arrays.toString(args);
return cache.computeIfAbsent(key, k -> {
try { return method.invoke(target, args); }
catch (Exception e) { throw new RuntimeException(e); }
});
}
}Proksi untuk Logika Percobaan Ulang
Bungkus pemanggilan metode dalam perulangan percobaan ulang. Jika terjadi pengecualian, coba lagi hingga N kali sebelum melemparkannya kembali.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
for (int attempt = 1; attempt <= 3; attempt++) {
try { return method.invoke(target, args); }
catch (InvocationTargetException e) {
if (attempt == 3) throw e.getCause();
Thread.sleep(1000L * attempt);
}
}
throw new RuntimeException("unreachable");
}Proksi untuk Pengelolaan Transaksi
@Transactional milik Spring menggunakan proksi dinamis untuk memulai transaksi sebelum pemanggilan metode dan melakukan commit atau rollback setelahnya—semuanya tanpa diketahui pemanggil.
Memeriksa Apakah Objek Merupakan Proksi
Gunakan Proxy.isProxyClass(obj.getClass()) untuk mendeteksi proksi, dan Proxy.getInvocationHandler(proxy) untuk mengambil penangannya.
if (Proxy.isProxyClass(service.getClass())) {
InvocationHandler h = Proxy.getInvocationHandler(service);
System.out.println("Handler: " + h.getClass().getSimpleName());
}Keterbatasan Proksi Dinamis JDK
Proksi dinamis JDK hanya bekerja dengan antarmuka—proksi ini tidak dapat digunakan untuk kelas konkret. Untuk membuat proksi berbasis kelas, gunakan CGLIB, yang juga digunakan Spring secara internal untuk kelas @Configuration.
CGLIB sebagai Alternatif
CGLIB membuat subkelas dari kelas target saat program berjalan dan menimpa semua metode yang tidak bersifat final. Spring menggunakannya jika tidak ada antarmuka. Tidak diperlukan anotasi—prosesnya transparan.
Proksi dalam Hibernate
Hibernate memuat asosiasi entitas secara malas menggunakan proksi CGLIB/Byte Buddy. Saat Anda mengakses koleksi yang dimuat secara malas, proksi tersebut menjalankan kueri basis data.
// Hibernate creates a proxy for:
@ManyToOne(fetch = FetchType.LAZY)
private Department department;
// Accessing dept triggers a DB query via the proxyPerforma Proksi
Pengiriman metode melalui proksi dinamis sekitar 5–10× lebih lambat daripada panggilan langsung. Untuk jalur yang sangat sering dijalankan, pertimbangkan pembuatan kode saat kompilasi (APT) atau MethodHandles sebagai pengganti proksi dinamis.
Pemeriksaan Singkat
Apa keterbatasan utama proksi dinamis JDK?
Rangkuman
Proksi dinamis JDK mencegat pemanggilan metode antarmuka melalui InvocationHandler. Gunakan untuk pencatatan, penyimpanan hasil, percobaan ulang, dan pengelolaan transaksi. Untuk membuat proksi kelas, gunakan CGLIB. Simpan hasil pembuatan proksi dalam cache karena proses tersebut menggunakan refleksi dan tidak gratis.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Proksi Dinamis dengan InvocationHandler” gratis?
Ya — teks lengkap “Proksi Dinamis dengan InvocationHandler” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Java Academy, upgrade ke CoddyKit PRO. Kursus Java Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Proksi Dinamis dengan InvocationHandler”?
Buat proksi dinamis JDK untuk mencegat pemanggilan metode interface demi pencatatan, caching, dan percobaan ulang. Kamu berlatih Java Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Java Academy?
Tidak diperlukan pengalaman sebelumnya. Java Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “Proksi Dinamis dengan InvocationHandler” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Java Academy ini?
Ya. Setiap pelajaran Java Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Inspeksi Class dengan Reflection
- Memanggil Metode dan Mengakses Field
- Proksi Dinamis dengan InvocationHandler
- Kinerja Reflection dan Alternatifnya