Dasar-Dasar: Ini membutuhkan ide-ide desain yang berorientasi pada objek, ide-ide polimorfik, dan ide-ide refleksi;
Munculnya mekanisme proxy dinamis Java memungkinkan pengembang Java untuk secara dinamis mendapatkan kelas proxy tanpa harus menulis kelas proxy secara manual. Kelas proxy bertanggung jawab untuk mengirim semua panggilan metode ke objek delegasi untuk mencerminkan eksekusi. Selama proses eksekusi pengiriman, pengembang juga dapat menyesuaikan objek delegasi dan fungsinya sesuai kebutuhan. Ini adalah kerangka proxy yang sangat fleksibel dan fleksibel. Dengan membaca artikel ini, pembaca akan memiliki pemahaman yang lebih dalam tentang mekanisme proxy dinamis Java. Artikel ini pertama -tama menganalisis kode berdasarkan mekanisme operasi dan karakteristik proxy dinamis Java dan mendeduksi implementasi internal kelas pembuatan dinamis.
Konsep Dasar dan Klasifikasi Model Agen
Mode proxy: Menyediakan proxy untuk objek lain untuk mengontrol akses ke objek ini. Objek proxy bertindak sebagai perantara, dan dapat menghapus layanan atau menambahkan layanan tambahan, atau mengutip orang lain: "Kelas proxy bertanggung jawab untuk pesan pra-pemrosesan untuk kelas delegasi, memfilter pesan dan penerusan pesan, dan melakukan pemrosesan selanjutnya setelah pesan dieksekusi oleh kelas delegasi."
Skenario aplikasi mode agen dalam pengembangan
Proxy jarak jauh: Menyediakan objek perwakilan LAN untuk objek dari berbagai wilayah geografis.
Agen Virtual: Tunda objek yang mengonsumsi banyak sumber daya sesuai kebutuhan dan membuatnya ketika mereka benar -benar dibutuhkan. Misalnya, teks ditampilkan terlebih dahulu dan kemudian gambar ditampilkan di halaman web.
Agen Perlindungan: Mengontrol hak akses pengguna yang berbeda. Misalnya: Hanya setelah pendaftaran pelanggan berhasil dapat menambah, menghapus, memodifikasi, dan memeriksa operasi dilakukan.
Agen Referensi Cerdas: Menyediakan layanan tambahan untuk agen target.
Cara mengimplementasikan mode proxy
Mana yang lebih baik untuk mengimplementasikan proxy dinamis menggunakan warisan dan agregasi!
Antarmuka Publik Bergerak {public void move ();} Mobil kelas publik mengimplementasikan bergerak {@Override public void move () {try {thread.sleep (baru acak (). nextInt (1000)); System.out.println ("... driving ...");} Catch (interupted exception e) {// too-auto-gener auto-gener (oMen (classion); Car2 memperluas car {@override public void move () {// Pisahkan kode, tingkatkan logika bisnis start waktu = system.currentTimeMillis (); System.out.println ("Mobil mulai mengemudi ..."); super.move (); long endtime = system.currentTimeMillis (); System.out.print (); endtime long endtime = system.currentTimeMillis (); System.out.printe (); endtime long endtime = system.currentTimeMillis (); System.out.printe "+(endtime-starttime)+" ms ");}}Metode waris untuk mengimplementasikan proxy
Moveablecar2=newCar2();
car2.move();
Metode agregasi mengimplementasikan proxy
Carcar=newCar();
Moveablem=newCar3(car);
m.move();
Meringkaskan
Metode warisan tidak cukup fleksibel. Ketika fungsi ditumpangkan, Anda hanya dapat memperluas kelas proxy yang membengkak;
Menggunakan agregasi, agen dapat diteruskan satu sama lain, dan proxy dapat digabungkan secara fleksibel;
Carlogproxy kelas publik memperluas mobil {@override public void move () {// Pisahkan kode dan tingkatkan logika bisnis start waktu = System.currentTimeMillis (); System.out.println ("Login endn (); System (); System.currentln (); CARTIMEPROXY mengimplementasikan bergerak {cartimeproxy umum (mobil mobil) {super (); this.car = car;} carcar pribadi; @override public move () {// pisahkan kode dan tambahkan logika bisnis start waktu = System.currentTiMillis (); System.out.println ("The Car Starts To Car start. endTime=System.currentTimeMillis();System.out.println("The car ends to drive... Time: "+(endTime-startTime)+"ms");}}@Test: Car car =new Car();CarTimeProxy ctp=new CarTimeProxy(car);CarLogProxy clp=new CarLogProxy(ctp);clp.move();//You juga dapat meneruskan instance proxy satu sama lain melalui antarmuka carlogproxy clp1 = new carlogproxy (car); cartimeproxy ctp1 = cartimeproxy baru (clp1); ctp1.move ();JDK Dynamic Proxy dan CGLIB Dynamic Proxy
JDK Dynamic Proxy
Implementasi Agen
Apa yang harus dilakukan jika objek yang berbeda ingin mengimplementasikan kelas proxy dengan fungsi yang sama?
Pada saat ini, Anda dapat mencoba mengintegrasikannya di kelas proxy yang sama ------- proxy dinamis: mengimplementasikan proxy untuk kelas/metode yang berbeda;
Proses umum adalah sebagai berikut:
Kelas proxy dinamis Java terletak di bawah paket java.lang.reflect, yang umumnya terutama melibatkan dua kelas berikut:
(1) InterfaceInvocationHandler: Hanya satu metode yang didefinisikan dalam antarmuka ini PublicObjectInvoke (ObjectObj, MethodMethod, Object [] args)
OBJ: Umumnya mengacu pada kelas proxy
Metode: adalah metode proxy
Args adalah array parameter untuk metode ini.
Metode abstrak ini diimplementasikan secara dinamis di kelas proxy.
(2) Proxy: Kelas ini adalah kelas proxy yang dinamis
statixObjectnewProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandlerh)
Mengembalikan contoh kelas glikosida, dan kelas proxy yang dikembalikan dapat digunakan sebagai kelas proxy (Anda dapat menggunakan metode yang dinyatakan dalam antarmuka oleh kelas proxy);
Contoh Implementasi:
@ TimHandler Kelas Publik TimHandler mengimplementasikan InvocationHandler {public timhandler (objek target) {super (); this.target = target;} private objectTarget;/* parameter:* Metode Proxy Proxy* Metode THROWABLE Objek Proxy* Parameter Args** Return Nilai: Metode Objek Pengembalian Nilai Return*/@@ override Objek Objek Proxy* Parameter Args* startTime = system.currentTimeMillis (); System.out.println ("Mobil mulai dikendarai ..."); Method.invoke (target); panjang akhir waktu = System.currentTimeMillis (); System.out.println ("Mobil berakhir untuk mengendarai ... waktu:"+(endtime-starttime)+"ms"); @Antarmuka Antarmuka Publik kelas proxy bergerak {public void move ();}@kelas proxy public class Car implements Moveable{@Override public void move() {try {Thread.sleep(new Random().nextint(1000));System.out.println("...driving...");}catch (InterruptedException e) {// TODO Auto-generated catch block e.printStackTrace();}}}@tes
Tes Kelas Publik { / *** JDK Dynamic Proxy Test Class* / Public Static Void Main (String [] args) {mobil mobil = mobil baru (); InvocationHandler h = new timHandler (mobil); Kelas <?> Cls = car.getClass (); /** Loader Class Loader* Antarmuka mengimplementasikan antarmuka* h InvocationHandler*/ movable m = (movable) proxy.newproxyInstance (cls.getClassLoader (), cls.getInterfaces (), h); m.move (); }}&& Hasil tes
Ringkasan
DynamicProxy adalah kelas seperti itu:
Ini adalah kelas yang dihasilkan saat runtime. Kelas ini perlu menerapkan serangkaian antarmuka. Saat menggunakan kelas proxy dinamis, antarmuka InvocationHandler harus diimplementasikan.
Langkah Umum untuk Proxy Dinamis JDK
1. Buat kelas yang mengimplementasikan antarmuka InvocationHandler, yang harus menerapkan Invoke ()
2. Buat kelas proxy dan antarmuka
3. Metode Statis Proxy Hubungi untuk membuat kelas proxy
NewProxyInstance (ClassLoadererer, Class [] Antarmuka, InvocationHandlerh)
4. Metode panggilan melalui proxy
Implementasi proxy dinamis CGLIB
Implementasi Agen
@Paket CGLIB-NODE-2.2.Jar
@Cglibproxy intersepsi kelas mengimplementasikan metode interface methodIntercept: menulis ulang metode intersep
Kelas Publik CGLIBPROXY mengimplementasikan MethodInterceptor {private EnhancerenHancer = new Enhancer (); objek publik getProxy (kelas cl) {// atur kelas yang membuat subkelas penambah. args method* proxy instance of proxy class* */@Override public Object intercept(Object obj, Method m,Object[] args, MethodProxy proxy)throws Throwable {System.out.println("Login start...");//The proxy class calls the parent class's method proxy.invokeSuper(obj, args);System.out.println("Login end...");return null;}}@Proxy Class Train
kereta kelas publik {public void move () {System.out.println ("Kereta mengemudi ..."); }}@Test kelas
tes kelas publik { / *** CGLIBPROXY Kelas tes proxy dinamis* / public static void main (string [] args) {cglibproxy proxy = new cglibproxy (); Train t = (train) proxy.getproxy (train.class); t.move (); }}Hasil tes ##:
Ringkasan
Langkah Umum Untuk Mengimplementasikan Proksi Dinamis Menggunakan CGlibproxy
1. Buat kelas untuk mengimplementasikan antarmuka MethodInterceptor dan mengganti metode intersep
2. Buat kelas proxy
3. Hubungi metode khusus kelas proxy untuk mendapatkan instance proxy
4. Panggil metode yang perlu dieksekusi oleh instance proxy
Ringkasan komparatif
JDK Dynamic Proxy
1. Hanya kelas proxy yang menerapkan antarmuka
2. Kelas tanpa antarmuka tidak dapat mengimplementasikan proxy dinamis untuk JDK
Proxy Dinamis CGlib
1. Menerapkan proxy untuk kelas
2. Hasilkan subkelas ke kelas target eksekusi, dan gunakan metode mencegat teknologi untuk mencegat semua panggilan metode kelas induk.
Simulasi langkah pembuatan agen
Ide:
Fungsi Implementasi: Mengembalikan objek proxy melalui NewProxyInstance dari proxy
1. Deklarasikan sepotong kode sumber (agen pembuatan dinamis)
2. Kompilasi Kode Sumber (JDKCompilerAPI) untuk menghasilkan kelas baru (kelas proxy)
3. Muat kelas ini ke dalam memori dan hasilkan objek baru (objek proxy)
4. Kembalikan objek proxy
Tingkatkan Implementasi Proksi Dinamis
Pertama, kami mendapatkan kompiler sistem, mendapatkan file manajer melalui kompiler, dan kemudian mendapatkan file. Kompiler kemudian melakukan tugas kompilasi. Setelah menyelesaikan kompilasi, kami memuat file kelas ke dalam class loader, dapatkan instance melalui metode konstruktor, dan kemudian hubungi newInstance () untuk menerima instance objek.
(1) Dapatkan kompiler javaCompilerCompiler = toolprovider.getsystemjavaCompiler ();
(2) File Manager StandardJavaFileManagerFileMgr = compiler.getstandardFileManager (null, null, null);
(3) Dapatkan file iterableunits = filemgr.getJavaFileObjects (nama file);
(4) kompilasi Tugas KompilasiTaskt = compiler.getask (null, filemgr, null, null, null, null, unit);
(5) Muat ke memori
Classloadercl = classloader.getSystemClassLoader ();
Classc = cl.LoadClass ("com.imooc.proxy. $ Proxy0");
(6) Bangun instance melalui konstruktor objek proxy
Constructorctr = c.getConstructor (infce);
CTR.NewInstance (newcar ());
--------
Seperti disebutkan di atas, logika bisnis internal adalah kode-kode. Bagaimana menerapkan proxy dinamis yang sebenarnya dan logika bisnis yang ditunjuk secara dinamis?
1. Anda perlu membuat prosesor transaksi. Pertama, Anda membuat antarmuka, yaitu, InvocationHandler. Untuk mensimulasikan JDK, nama antarmuka sama dengan nama prosesor transaksi JDK. Anda juga menulis metode yang disebut Invoke (), yang digunakan untuk mewakili metode tertentu dari suatu objek untuk pemrosesan bisnis. Oleh karena itu, Anda perlu meneruskan objek tertentu dan metode objek sebagai parameter dari metode Invoke (). Invoke (ObjectObj, MethodMethod), metode yang digunakan sebagai parameter untuk refleksi Java, dan paket ini perlu diperkenalkan. Dengan cara ini, antarmuka InvocationHandler selesai.
2. Buat kelas implementasi pemrosesan transaksi, seperti timerproxy, untuk mengimplementasikan antarmuka InvocationHandler, sehingga strukturnya menjadi
――6―6 - TimerProxyImplementsInVocationHandler { ―6666666 secara ―6666666 secaraAnda perlu meneruskan objek target. Jika Anda tidak memiliki parameter, Anda tidak dapat menulis parameter. Buat metode konstruksi objek proxy dan inisialisasi objek target.
3. Dalam metode newProxyInstance () dari kelas proxy, selain menggunakan antarmuka kelas target sebagai parameter, Anda juga perlu lulus Invocation Handller Prosesor Transaksi, dan kemudian mengubah bagian yang dikodekan dari objek instance yang dibuat dan menggunakan metode prosesor transaksi untuk menggantinya. Kesulitannya terletak pada penyambungan string.
Meringkaskan
Dalam proyek kami, pola agen memiliki signifikansi praktis sendiri. Misalnya, jika kami ingin menelepon kelas di bawah paket JAR tertentu, kami dapat menambahkan beberapa logika bisnis khusus sebelum menelepon kelas ini. Metode ini juga disebut pemrograman berorientasi AOP. (Tambahkan fungsi tambahan tanpa mengubah fungsi asli.)
Di atas adalah semua penjelasan terperinci dari kode proxy dinamis Java (pola desain) dalam artikel ini, saya harap ini akan membantu semua orang. Teman yang tertarik dapat terus merujuk ke topik terkait lainnya di situs ini. Jika ada kekurangan, silakan tinggalkan pesan untuk menunjukkannya. Terima kasih teman atas dukungan Anda untuk situs ini!