@Transactional @async dan anotasi lainnya tidak berhasil
Sebelumnya, banyak orang telah mengalami beberapa situasi di mana anotasi tidak berfungsi saat menggunakan @transactional, @Async dan anotasi lainnya di musim semi.
Mengapa situasi ini terjadi? Karena fungsi anotasi ini sebenarnya diimplementasikan oleh Spring AOP, dan prinsip implementasinya diimplementasikan melalui proxy.
JDK Dynamic Proxy
Mari kita pahami prinsip -prinsip dasar proxy dinamis JDK dengan contoh sederhana:
// Antarmuka Antarmuka Kelas Target JDKProxyTestService {void run ();} // kelas target kelas publik JDKProxyTestServiceImpl mengimplementasikan JDKProxyTestService {public void run () {System.out.println ("lakukan sesuatu ..."); }} // kelas proxy kelas publik testJDKproxy mengimplementasikan InvocationHandler {private objek targetObject; // Objek target proxy // Bangun objek proxy objek publik newProxy (objek targetObject) {this.targetObject = targetObject; return proxy.newproxyInstance (targetObject.getClass (). getClassLoader (), targetObject.getClass (). getInterfaces (), this); } // Gunakan refleksi untuk melakukan peningkatan logis pada logika asli objek Invoke (objek proxy, metode metode, objek [] args) melempar lempar {// simulasikan transaksi mulai asumsumebeGintransaction (); // Objek Eksekusi Asli Ret = Method.Invoke (TargetObject, args); // Pengajuan Transaksi Mock AssumeCommitTransaction (); kembali kembali; } private void assumebeGintransaction () {System.out.println ("Mulai transaksi mock ..."); } private void asseCommitTransaction () {System.out.println ("Pengajuan Transaksi Mock ..."); }} // uji tes kelas publik {public static void main (string [] args) {testjDkproxy jDkproxy = new testjdkProxy (); Jdkproxytestservice proxy = (jdkproxytestservice) jdkproxy.newproxy (jdkproxytestserviceImpl ()); proxy.run (); }}Contoh di atas harus dapat menjelaskan dengan jelas prinsip proxy dinamis JDK. Ini menggunakan mekanisme refleksi untuk menghasilkan kelas anonim yang mengimplementasikan antarmuka proxy, dan memanggil Invokhandler untuk menanganinya sebelum memanggil metode spesifik. Ketika kami memanggil metode melalui objek kelas proxy, kami benar -benar akan memanggil metode Invoke terlebih dahulu, dan kemudian memanggil metode asli. Dengan cara ini, kita dapat menambahkan logika pemrosesan secara seragam sebelum dan sesudah logika metode asli.
Spring juga memiliki metode proxy dinamis yang merupakan proxy dinamis CGLIB. Ini memuat file kelas dari kelas objek proxy dan memprosesnya dengan memodifikasi bytecode -nya untuk menghasilkan subclass. Meskipun metode penanganannya berbeda, ide -ide agensi konsisten.
Jika objek target yang diproklikan mengimplementasikan antarmuka, Spring akan menggunakan proxy dinamis JDK secara default. Semua antarmuka yang diimplementasikan oleh tipe target ini akan diproksi. Jika objek target tidak mengimplementasikan antarmuka apa pun, proxy CGLIB dibuat.
Kegagalan dan resolusi anotasi AOP musim semi
Berdasarkan analisis di atas dari prinsip proxy dinamis, mari kita lihat dua masalah umum berikut:
Di kelas yang sama, metode panggilan metode B (dijelaskan pada metode B), dan anotasi tidak valid.
Untuk semua anotasi AOP musim semi, jika Spring menemukan anotasi seperti itu saat memindai kacang, ia secara dinamis akan membangun objek proxy.
Anotasi ini valid jika Anda ingin secara langsung memanggil metode A dengan anotasi melalui objek Kelas X. Karena pada saat ini, Spring akan menentukan bahwa ada anotasi AOP pada metode yang akan Anda hubungi, dan kemudian akan menggunakan objek proxy dari Metode Kelas X untuk memanggil A.
Tetapi misalkan metode itu A di kelas X akan memanggil metode B dengan anotasi, dan Anda masih ingin memanggil metode A melalui objek kelas X, maka anotasi pada metode B tidak valid. Karena Spring menentukan bahwa A yang Anda panggil tidak memiliki anotasi, objek asli masih digunakan daripada objek proxy. Ketika A panggilan B berikutnya, anotasi metode B pada objek asli tentu saja tidak valid.
Larutan:
Cara termudah tentu saja adalah membuat metode A dan B tidak memiliki ketergantungan dan dapat secara langsung memanggil metode B melalui objek kelas X.
Tetapi berkali -kali, logika kita mungkin tidak ditulis dengan baik dengan cara ini, jadi ada metode lain: temukan cara untuk secara manual mendapatkan objek proxy.
Kelas AOPContext memiliki metode CurrentProxy () yang dapat secara langsung mendapatkan objek proxy dari kelas saat ini. Maka contoh di atas dapat diselesaikan seperti ini:
// Metode Panggilan B Di dalam Metode A // 1. Panggilan B secara langsung, anotasi tidak valid. B () // 2. Dapatkan objek kelas proxy dan hubungi B. ((x) aopcontext.currentproxy ()). B ()
Objek @Autowired adalah nol dalam metode anotasi AOP
Dalam penggunaan sebelumnya, dalam metode anotasi, ketika menggunakan objek yang disuntikkan lainnya, ditemukan bahwa objek itu tidak disuntikkan, dan itu nol.
Akhirnya, ditemukan bahwa alasan untuk ini adalah karena metode itu pribadi. Karena Spring menggunakan proxy dinamis JDK atau proxy dinamis CGLIB, satu adalah kelas yang mengimplementasikan antarmuka dan yang lainnya diimplementasikan melalui subkelas. Baik antarmuka maupun kelas induk, metode pribadi tidak dapat ada, jika tidak, baik subkelas maupun kelas implementasi tidak dapat diganti.
Jika metode ini pribadi, maka metode ini tidak dapat ditemukan dalam proses proxy, menyebabkan masalah dalam pembuatan objek proxy dan menyebabkan beberapa objek tidak disuntikkan.
Jadi jika metode perlu menggunakan anotasi AOP, atur ke metode non-pribadi.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.