Proksi Dinamik dengan InvocationHandler
Cipta proksi dinamik JDK untuk memintas panggilan kaedah antara muka bagi pengelogan, pencachean dan percubaan semula.
Proksi Dinamik dengan InvocationHandler ialah pelajaran Java Academy percuma di CoddyKit. Ini ialah pelajaran 3 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Java Academy, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Java Academy merangkumi sejumlah 4 pelajaran.
Apakah Itu Proksi Dinamik?
Proksi dinamik JDK ialah objek yang dicipta pada masa jalan dan melaksanakan satu atau lebih antara muka. Semua panggilan kaedah dihantar kepada InvocationHandler yang anda sediakan.
Mencipta Proksi dengan Proxy.newProxyInstance
Panggil Proxy.newProxyInstance(classLoader, interfaces[], handler) untuk mencipta proksi. Proksi tersebut melaksanakan semua antara muka yang disenaraikan.
UserService proxy = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(),
new Class[]{UserService.class},
new LoggingHandler(realService)
);
proxy.findById(42L); // intercepted by LoggingHandlerAntara Muka InvocationHandler
Laksanakan InvocationHandler untuk mengendalikan setiap panggilan kaedah. Pengendali menerima objek proksi, kaedah 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 Caching
InvocationHandler boleh cache hasil: jika cache mengandungi hasil untuk argumen tersebut, kembalikannya; jika tidak, panggil kaedah sebenar 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 Logik Percubaan Semula
Bungkus panggilan kaedah dalam gelung percubaan semula. Jika berlaku pengecualian, cuba semula sehingga N kali sebelum melontarkannya semula.
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 Pengurusan Transaksi
@Transactional Spring menggunakan proksi dinamik untuk memulakan transaksi sebelum panggilan kaedah dan melakukan commit atau rollback selepasnya — semuanya tanpa pengetahuan pemanggil.
Menyemak Sama Ada Objek ialah Proksi
Gunakan Proxy.isProxyClass(obj.getClass()) untuk mengesan proksi dan Proxy.getInvocationHandler(proxy) untuk mendapatkan pengendalinya.
if (Proxy.isProxyClass(service.getClass())) {
InvocationHandler h = Proxy.getInvocationHandler(service);
System.out.println("Handler: " + h.getClass().getSimpleName());
}Had Proksi Dinamik JDK
Proksi dinamik JDK hanya berfungsi dengan antara muka — proksi ini tidak boleh digunakan untuk kelas konkrit. Untuk proksi berasaskan kelas, gunakan CGLIB, yang turut digunakan secara dalaman oleh Spring untuk kelas @Configuration.
CGLIB sebagai Alternatif
CGLIB menjana subkelas bagi kelas sasaran pada masa jalan dan mengatasi semua kaedah yang bukan final. Spring menggunakannya apabila tiada antara muka tersedia. Tiada anotasi diperlukan — proses ini telus.
Proksi dalam Hibernate
Hibernate memuatkan persatuan entiti secara malas menggunakan proksi CGLIB/Byte Buddy. Apabila anda mengakses koleksi malas, proksi itu mencetuskan pertanyaan SQL.
// Hibernate creates a proxy for:
@ManyToOne(fetch = FetchType.LAZY)
private Department department;
// Accessing dept triggers a DB query via the proxyPrestasi Proksi
Penghantaran kaedah melalui proksi dinamik adalah kira-kira 5–10× lebih perlahan daripada panggilan langsung. Untuk laluan yang sangat kritikal, pertimbangkan penjanaan kod pada masa kompilasi (APT) atau MethodHandles berbanding proksi dinamik.
Semakan Pantas
Apakah had utama proksi dinamik JDK?
Ringkasan
Proksi dinamik JDK memintas panggilan kaedah antara muka melalui InvocationHandler. Gunakannya untuk pengelogan, caching, percubaan semula dan pengurusan transaksi. Untuk proksi kelas, gunakan CGLIB. Cache penciptaan proksi — proses ini menggunakan refleksi dan bukan percuma.
Pelajari Java dengan tutor kecerdasan buatan — percuma
Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.
- Kursus
- 104
- Pelajaran
- 374
Soalan Lazim
Adakah pelajaran “Proksi Dinamik dengan InvocationHandler” percuma?
Ya — teks penuh “Proksi Dinamik dengan InvocationHandler” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Java Academy, tingkat taraf kepada CoddyKit PRO. Kursus Java Academy merangkumi sejumlah 4 pelajaran.
Apakah yang akan saya pelajari dalam “Proksi Dinamik dengan InvocationHandler”?
Cipta proksi dinamik JDK untuk memintas panggilan kaedah antara muka bagi pengelogan, pencachean dan percubaan semula. Anda berlatih Java Academy menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.
Adakah saya memerlukan pengalaman untuk memulakan Java Academy?
Tiada pengalaman terdahulu diperlukan. Pembelajaran Java Academy di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 3 daripada 4.
Berapa lamakah pelajaran “Proksi Dinamik dengan InvocationHandler” diambil?
Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.
Bolehkah saya menulis dan menjalankan kod dalam pelajaran Java Academy ini?
Ya. Setiap pelajaran Java Academy menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.
Semua pelajaran dalam kursus ini
- Pemeriksaan Kelas dengan Refleksi
- Memanggil Kaedah dan Mengakses Medan
- Proksi Dinamik dengan InvocationHandler
- Prestasi Refleksi dan Alternatif