Pemberitahuan musim semi AOP dibagi menjadi lima kategori:
Sebelum saran: Jalankan di depan titik koneksi. Pratinjau tidak akan mempengaruhi pelaksanaan titik koneksi kecuali pengecualian dilemparkan ke sini.
Pemberitahuan Pengembalian Normal [Setelah saran kembali]: Eksekusi setelah eksekusi normal dari titik koneksi selesai. Jika pengecualian dilemparkan oleh titik koneksi, itu tidak akan dieksekusi.
Pemberitahuan Pengembalian Pengecualian [Setelah Lempar Saran]: Eksekusi setelah pengecualian dilemparkan oleh titik koneksi.
Pemberitahuan Pengembalian [Setelah (akhirnya) Saran]: Setelah eksekusi selesai, isi pemberitahuan pengembalian akan dieksekusi apakah selesai secara normal atau pengecualian dilemparkan.
Di sekitar saran: di sekitar saran mengelilingi titik koneksi, seperti sebelum dan sesudah panggilan metode. Ini adalah jenis pemberitahuan yang paling kuat, yang dapat menyesuaikan beberapa operasi sebelum dan sesudah panggilan metode.
Pemberitahuan di sekitarnya juga perlu memutuskan apakah akan terus memproses titik bergabung (memanggil metode proses dari ProcePingJoinPoint) atau mengganggu eksekusi.
Selanjutnya, kami akan menguji lima jenis pemberitahuan dengan menulis program sampel:
Tentukan antarmuka
Paket com.chenqa.springaop.example.service; antarmuka publik BankService { / *** Transfer bank yang disimulasikan* @param dari akun* @param ke akun* @param Jumlah transfer akun* @return* / transfer boolean publik (formulir string, string ke, akun ganda);}Tulis kelas implementasi
package com.chenqa.springaop.example.service.impl;import com.chenqa.springaop.example.service.BankService;public class BCMBankServiceImpl implements BankService { public boolean transfer(String form, String to, double account) { if(account<100) { throw new IllegalArgumentException("Minimum transfer amount cannot be less than 100 yuan "); } System.out.println (Formulir+"Transfer ke"+ke+"Akun Bank"+Akun+"Yuan"); mengembalikan false; }}Ubah file konfigurasi pegas dan tambahkan yang berikut:
<!-BankService Bean-> <bean id = "BankService"/> <!-bagian-> <bean id = "myaspect"/> <!-aop konfigurasi-> <aop: config> <aop: aspek ref = "myaspect"> <aop: pointcut ekspresi = "eksekusi (*com.chenqa.spling.spl. id="pointcut"/> <aop:before method="before" pointcut-ref="pointcut"/> <aop:after method="after" pointcut-ref="pointcut"/> <aop:after-returning method="afterReturning" pointcut-ref="pointcut"/> <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut"/> <aop:around Method = "sekitar" pointcut-ref = "pointcut"/> </aop: aspek> </aop: config>
Menulis Program Tes
ApplicationContext Context = new ClassPathXMLapPlicationContext ("spring-aop.xml"); BankService BankService = Context.getBean ("BankService", BankService.class); BankService.Transfer ("Zhang San", "Li Si", 200); Output setelah eksekusi:
Ubah 200 dalam program pengujian menjadi 50, dan kemudian output setelah eksekusi:
Dari hasil tes, dapat dilihat bahwa urutan eksekusi dari lima pemberitahuan adalah:
Pra-notifikasi → Pemberitahuan surround → Pemberitahuan pengembalian normal/pemberitahuan pengembalian pengecualian → Pemberitahuan pengembalian, Anda dapat melakukan beberapa kali untuk dilihat.
Kasus 1: Metode hanya dicegat oleh satu kelas aspek
Ketika suatu metode dicegat hanya dengan satu aspek, dalam urutan apa saran berbeda dalam aspek ini dieksekusi? Silakan lihat:
Tambahkan kelas pointcut
Pointcut ini digunakan untuk mencegat semua metode di semua kelas di bawah paket pengujian.
Paket tes; import org.aspectj.lang.annotation.pointcut; pointcut kelas publik {@pointcut (value = "di dalam (test.*)") public void aopdemo () {}}Tambahkan Kelas Aspek
Saran di kelas ini akan menggunakan pointcut di atas. Silakan merujuk ke atribut nilai dari setiap saran saat menggunakannya.
Paket Tes; impor org.aspectj.lang.joinpoint; impor org.aspectj.lang.proedingnointpoint; impor org.aspectj.lang.annotation.*; impor org.springframework.stereotipe.sponent;@component@aspectpublic class aspect1 {@before (value = "test. joinpoint) {System.out.println ("[aspek1] sebelum saran"); } @Around (value = "test.pointcuts.aopdemo ()") public void sekitar (ProsedingjOnpoint pjp) melempar Throwable {System.out.println ("[aspek1] di sekitar saran 1"); pjp.proed (); System.out.println ("[aspek1] di sekitar saran2"); } @AfterReturning (value = "test.pointcuts.aopdemo ()") batal public afterreturning (joinpoint goinpoint) {System.out.println ("[aspek1] afterreturning nasihat"); } @AfterThrowing (value = "test.pointcuts.aopdemo ()") public void afterthrowing (joinpoint goinpoint) {System.out.println ("[aspek1] nasihat afterthrowing"); } @After (value = "test.pointcuts.aopdemo ()") public void setelah (joinpoint gabungan) {System.out.println ("[aspek1] nasihat afterthrowing"); } @After (value = "test.pointcuts.aopdemo ()") public void setelah (gabungan joinpoint) {System.out.println ("[aspek1] setelah nasihat"); }}Tambahkan pengontrol tes
Tambahkan pengontrol untuk pengujian. Hanya ada satu metode dalam pengontrol ini, tetapi akan menangani secara berbeda sesuai dengan nilai parameter: satu adalah mengembalikan objek secara normal, dan yang lainnya adalah untuk melempar pengecualian (karena kami ingin menguji nasihat @FterThrowing)
Tes Paket; Impor Test.Exception.testException; impor org.springframework.http.httpstatus; impor org.springframework.web.bind.annotation.*;@restcontroller@requestMapping (value = "/aop") kelas publik aoptestcontroller@@@ronpatus (value = "/aop") @RequestMapping (value = "/test", Method = requestMethod.get) Tes Hasil Publik (@RequestParam Boolean ThrowException) {// case 1 if (throwexception) {System.out.println ("Lempar pengecualian"); Lempar TestException baru ("Mock A Server Exception"); } // case 2 system.out.println ("test ok"); return new result () {{this.setId (111); this.setname ("Mock a Hasil"); }}; } Hasil kelas statis publik {private int id; nama string pribadi; publik int getId () {return id; } public void setid (int id) {this.id = id; } public string getName () {return name; } public void setName (name string) {this.name = name; }}}Uji situasi normal
Masukkan URL berikut langsung di browser dan masukkan: http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=false 1
Kami akan melihat hasil output:
[Aspek1] seputar nasihat 1 [aspek1] Sebelum saran ok [aspek1] seputar saran2 [aspek1] setelah saran [aspek1] setelah kembali nasihat
Pengecualian tes
Langsung masukkan URL berikut di browser dan tekan Enter: http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=true 1
Kami akan melihat hasil output:
[Aspek1] seputar nasihat 1 [aspek1] Sebelum menasihati pengecualian [aspek1] setelah nasihat [aspek1] nasihat setelahnya
sebagai kesimpulan
Ketika suatu metode dicegat oleh hanya satu kelas aspek, saran di dalam kelas aspek akan dieksekusi dalam urutan berikut:
Situasi Normal:
Pengecualian:
Kasus 2: Metode yang sama dicegat oleh beberapa kelas aspek
Berikut adalah contoh yang dicegat oleh dua kelas aspek.
Dalam beberapa kasus, untuk dua kelas aspek yang berbeda, terlepas dari apakah saran mereka menggunakan pointcut yang sama atau pointcuts yang berbeda, dapat menyebabkan metode yang sama dicegat oleh beberapa kelas aspek. Jadi, dalam hal ini, dalam urutan apa saran di beberapa kelas aspek ini dijalankan? Silakan lihat:
Kelas pointcut tetap tidak berubah
Tambahkan kelas aspek baru
Paket Tes; impor org.aspectj.lang.joinpoint; impor org.aspectj.lang.proedingnointpoint; impor org.aspectj.lang.annotation.*; impor org.springframework.stereotipe.sponent;@component@aspectpublic class aspect2 {@before (value = "test. joinpoint) {System.out.println ("[aspek] sebelum saran"); } @Around (value = "test.pointcuts.aopdemo ()") public void sekitar (ProsedingjOnpoint pjp) melempar Throwable {System.out.println ("[aspek2] di sekitar saran 1"); pjp.proed (); System.out.println ("[aspek2] di sekitar saran2"); } @Afterreturning (value = "test.pointcuts.aopdemo ()") public void afterreturning (joinpoint goinpoint) {System.out.println ("[aspek2] aftereturning nasihat"); } @AfterThrowing (value = "test.pointcuts.aopdemo ()") public void afterthrowing (joinpoint goinpoint) {System.out.println ("[aspek2] nasihat afterthrowing"); } @After (value = "test.pointcuts.aopdemo ()") public void setelah (gabungan joinpoint) {system.out.println ("[aspek2] nasihat afterthrowing"); } @After (value = "test.pointcuts.aopdemo ()") public void setelah (gabungan joinpoint) {System.out.println ("[aspek2] setelah nasihat"); }}Pengontrol uji juga tidak berubah
Masih menggunakan pengontrol di atas. Tetapi sekarang baik Aspect1 dan Aspect2 mencegat metode dalam pengontrol.
Lanjutkan untuk menguji di bawah ini!
Uji situasi normal
Masukkan URL berikut langsung di browser dan masukkan: http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=false 1
Kami akan melihat hasil output:
[Aspek2] seputar nasihat 1 [aspek2] Sebelum saran [aspek1] seputar saran 1 [aspek1] Sebelum saran ok [aspek1] di sekitar nasihat2 [aspek1] setelah nasihat [aspek1] setelah memperbaiki nasihat [aspek2] di sekitar nasihat2 [aspek2] aftereturning nasihat
Tetapi pada saat ini, saya tidak dapat menyimpulkan bahwa aspek2 pasti dieksekusi sebelum aspek1.
Tidak percaya? Anda me -restart server dan mencoba lagi, mungkin Anda akan melihat hasil eksekusi berikut:
[Aspek1] seputar nasihat 1 [aspek1] Sebelum saran [aspek2] seputar saran 1 [aspek2] Sebelum saran ok [aspek2] seputar nasihat2 [aspek2] Setelah nasihat [aspek2] setelah memperbaiki nasihat [aspek1] di sekitar nasihat2 [aspek1] afterpeturning nasihat
Yaitu, dalam hal ini, urutan eksekusi Aspect1 dan Aspect2 tidak diketahui. Jadi bagaimana cara menyelesaikannya? Tidak terburu -buru, solusinya akan diberikan di bawah ini.
Pengecualian tes
Langsung masukkan URL berikut di browser dan tekan Enter: http://192.168.142.8:7070/aoptest/v1/aop/test?throwException=true 1
Kami akan melihat hasil output:
[Aspek2] seputar saran 1 [aspek] sebelum saran [aspek1] seputar nasihat 1 [aspek1] Sebelum menasihati pengecualian [aspek1] setelah melempar nasihat [aspek2] setelah melempar nasihat
Demikian pula, jika Anda memulai kembali server dan kemudian mengujinya lagi, Anda dapat melihat hasil berikut:
[Aspek1] seputar saran 1 [aspek1] Sebelum saran [aspek2] seputar saran 1 [aspek2] sebelum menasihati pengecualian [aspek2] setelah melontarkan nasihat [aspek1] setelah throwrowing nasihat
Dengan kata lain, dengan cara yang sama, urutan eksekusi Aspek1 dan Aspek2 juga tidak ditentukan dalam keadaan yang luar biasa.
Jadi dalam Kasus 2, bagaimana Anda menentukan urutan eksekusi dari setiap aspek?
Ada dua metode:
Tidak peduli metode mana yang digunakan, semakin kecil aspeknya, semakin banyak dieksekusi terlebih dahulu.
Misalnya, kami menambahkan anotasi @order untuk APSECT1 dan aspek masing -masing, sebagai berikut:
@Order (5)@component@aspectpublic kelas aspek1 {// ...}@order (6)@component@aspectpublic kelas aspek2 {// ...} Setelah modifikasi ini, dapat dipastikan bahwa dalam hal apa pun, saran dalam Aspect1 selalu dieksekusi sebelum saran dalam Aspek2. Seperti yang ditunjukkan pada gambar di bawah ini:
Catatan
Jika dua saran yang identik didefinisikan untuk titik yang sama (misalnya, dua @Before) didefinisikan, maka urutan eksekusi dari kedua saran ini tidak dapat ditentukan, bahkan jika Anda menambahkan anotasi @order ke dua saran ini, itu tidak akan berfungsi. Ingat ini.
Untuk saran @Around, terlepas dari apakah itu memiliki nilai pengembalian atau tidak, itu harus memanggil pjp.proed () di dalam metode; Kalau tidak, antarmuka dalam pengontrol tidak akan dieksekusi, yang juga akan menyebabkan nasihat @Before tidak dipicu. Misalnya, kami mengasumsikan bahwa dalam keadaan normal, perintah eksekusi adalah "aspek2 -> apsect1 -> controller". Jika kita menghapus pjp.proed (); di @around di aspek1, maka output yang kita lihat adalah:
[Aspek2] seputar nasihat 1 [aspek] sebelum saran [aspek1] seputar nasihat 1 [aspek1] di sekitar nasihat2 [aspek1] setelah nasihat [aspek1] setelah kembali nasihat [aspek2] di sekitar nasihat2 [aspek2] setelah memperbaiki nasihat
Dari hasilnya, kita dapat menemukan bahwa antarmuka dalam pengontrol belum dieksekusi, dan @BeforeAdvice di aspek1 belum dieksekusi.
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.