Melaksanakan Anotasi AOP Spring Custom

1. Pengenalan

Dalam artikel ini, kami akan menerapkan anotasi AOP khusus menggunakan sokongan AOP pada musim bunga.

Pertama, kami akan memberikan gambaran umum tahap tinggi mengenai AOP, menjelaskan apa itu dan kelebihannya. Setelah ini, kami akan melaksanakan anotasi kami selangkah demi selangkah, secara beransur-ansur membangun pemahaman yang lebih mendalam mengenai konsep AOP semasa kami berjalan.

Hasilnya akan menjadi pemahaman yang lebih baik mengenai AOP dan kemampuan untuk membuat anotasi musim bunga khas kami di masa hadapan.

2. Apa itu Anotasi AOP?

Untuk meringkaskan dengan cepat, AOP bermaksud pengaturcaraan berorientasikan aspek. Pada dasarnya, ini adalah cara untuk menambahkan tingkah laku ke kod yang ada tanpa mengubah kod itu .

Untuk pengenalan terperinci mengenai AOP, terdapat artikel mengenai potongan dan nasihat AOP. Artikel ini mengandaikan bahawa kita sudah mempunyai pengetahuan asas.

Jenis AOP yang akan kami laksanakan dalam artikel ini didorong oleh anotasi. Kita mungkin sudah biasa dengan ini jika kita menggunakan anotasi Spring @Transactional :

@Transactional public void orderGoods(Order order) { // A series of database calls to be performed in a transaction }

Kuncinya di sini adalah tidak menyerang. Dengan menggunakan meta-data anotasi, logik perniagaan teras kami tidak tercemar dengan kod transaksi kami. Ini menjadikannya lebih mudah untuk memikirkan, merefaktor, dan menguji secara berasingan.

Kadang-kadang, orang yang mengembangkan aplikasi Spring dapat melihatnya sebagai ' Spring Magic', tanpa memikirkan secara terperinci mengenai cara kerjanya. Sebenarnya, apa yang berlaku tidak begitu rumit. Namun, setelah kami menyelesaikan langkah-langkah dalam artikel ini, kami akan dapat membuat anotasi tersuai kami sendiri untuk memahami dan memanfaatkan AOP.

3. Ketergantungan Maven

Pertama, mari tambah pergantungan Maven kami.

Untuk contoh ini, kami akan menggunakan Spring Boot, kerana pendekatan konvensinya mengenai konfigurasi membolehkan kami bangun secepat mungkin:

 org.springframework.boot spring-boot-starter-parent 2.2.2.RELEASE    org.springframework.boot spring-boot-starter-aop  

Perhatikan bahawa kami telah memasukkan pemula AOP, yang menarik di perpustakaan yang kami perlukan untuk mula melaksanakan aspek.

4. Membuat Anotasi Kustom Kami

Anotasi yang akan kami buat adalah salah satu yang akan digunakan untuk mencatat jumlah masa yang diperlukan kaedah untuk dilaksanakan. Mari buat penjelasan kami:

@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface LogExecutionTime { } 

Walaupun pelaksanaannya agak sederhana, perlu diperhatikan untuk apa kedua-dua anotasi meta digunakan.

The @Target anotasi memberitahu kita di mana anotasi kami akan dikenakan. Di sini kita menggunakan ElementType.Method, yang bermaksud ia hanya akan berfungsi pada kaedah. Sekiranya kami cuba menggunakan anotasi di tempat lain, maka kod kami akan gagal disusun. Tingkah laku ini masuk akal, kerana penjelasan kami akan digunakan untuk masa pelaksanaan kaedah pembalakan.

Dan @Retention hanya menyatakan sama ada anotasi akan tersedia untuk JVM pada waktu runtime atau tidak. Secara lalai tidak, jadi Spring AOP tidak dapat melihat anotasinya. Inilah sebabnya mengapa ia dikonfigurasi semula.

5. Menciptakan Aspek Kita

Sekarang kita mempunyai penjelasan, mari buat aspek kita. Ini hanya modul yang akan merangkumi keperihatinan silang kita, yang mana kes kita adalah kaedah log masa pelaksanaan. Semua itu adalah kelas, dianotasi dengan @Aspect:

@Aspect @Component public class ExampleAspect { }

Kami juga menyertakan anotasi @Component , kerana kelas kami juga perlu menjadi kacang Spring untuk dikesan. Pada dasarnya, ini adalah kelas di mana kita akan melaksanakan logik yang mahu disuntikkan oleh anotasi tersuai kita.

6. Membuat Titik dan Nasihat Kami

Sekarang, mari buat kaedah dan nasihat kami. Ini akan menjadi kaedah anotasi yang sesuai dengan aspek kita:

@Around("@annotation(LogExecutionTime)") public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { return joinPoint.proceed(); }

Secara teknikal ini belum mengubah tingkah laku apa-apa, tetapi masih banyak perkara yang perlu dilakukan analisis.

Pertama, kami memberi penjelasan kaedah kami dengan @Around. Ini adalah nasihat kami, dan di sekitar nasihat bermaksud kami menambahkan kod tambahan baik sebelum dan sesudah pelaksanaan kaedah. Terdapat jenis nasihat lain, seperti sebelum dan sesudah tetapi mereka tidak akan terlepas dari ruang lingkup artikel ini.

Seterusnya, anotasi @Around kami mempunyai hujah pemotongan titik. Titik titik kami hanya mengatakan, 'Terapkan nasihat ini kaedah apa pun yang dijelaskan dengan @LogExecutionTime .' Terdapat banyak jenis potongan titik lain, tetapi ia akan ditinggalkan lagi jika ada ruang lingkup.

Kaedah logExecutionTime () itu sendiri adalah nasihat kami. Terdapat satu hujah, ProceedingJoinPoint. Dalam kes kami, ini akan menjadi kaedah pelaksanaan yang telah diberi penjelasan dengan @LogExecutionTime.

Akhirnya, apabila kaedah penjelasan kami akhirnya dipanggil, apa yang akan berlaku ialah nasihat kami akan dipanggil terlebih dahulu. Maka terserah kepada nasihat kami untuk memutuskan apa yang perlu dilakukan seterusnya. Dalam kes kami, nasihat kami adalah melakukan apa-apa selain memanggil teruskan (), yang merupakan kaedah memanggil anotasi asal sahaja.

7. Mencatat Masa Pelaksanaan Kami

Sekarang kita mempunyai rangka kita, yang perlu kita lakukan hanyalah menambahkan logik tambahan untuk nasihat kita. Inilah yang akan mencatat masa pelaksanaan selain memanggil kaedah asal. Mari tambahkan tingkah laku tambahan ini pada nasihat kami:

@Around("@annotation(LogExecutionTime)") public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); Object proceed = joinPoint.proceed(); long executionTime = System.currentTimeMillis() - start; System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms"); return proceed; }

Sekali lagi, kami tidak melakukan perkara yang sangat rumit di sini. Kami baru sahaja mencatatkan masa semasa, melaksanakan kaedah, kemudian mencetak jumlah masa yang diperlukan untuk konsol. Kami juga mencatat tandatangan kaedah, yang disediakan untuk menggunakan contoh gabungan. Kami juga dapat memperoleh akses ke maklumat lain jika kami mahu, seperti argumen kaedah.

Sekarang, mari cuba anotasi kaedah dengan @LogExecutionTime, dan kemudian jalankan untuk melihat apa yang berlaku. Perhatikan bahawa ini mestilah Spring Bean untuk berfungsi dengan betul:

@LogExecutionTime public void serve() throws InterruptedException { Thread.sleep(2000); }

Selepas pelaksanaan, kita akan melihat perkara berikut yang dilog masuk ke konsol:

void org.baeldung.Service.serve() executed in 2030ms

8. Kesimpulannya

Dalam artikel ini, kami memanfaatkan Spring Boot AOP untuk membuat anotasi tersuai kami, yang dapat kami gunakan pada kacang Spring untuk menyuntikkan tingkah laku tambahan kepada mereka pada waktu proses.

Kod sumber untuk aplikasi kami boleh didapati di GitHub; ini adalah projek Maven yang seharusnya dapat dijalankan seperti sedia kala.