Pengantar Jenis Saran di Musim Semi

1. Ikhtisar

Pada artikel ini, kami akan membahas berbagai jenis saran AOP yang dapat dibuat di Spring.

Saran adalah tindakan yang dilakukan oleh suatu aspek pada titik penghubung tertentu. Jenis nasihat yang berbeda mencakup nasihat "sekitar", "sebelum" dan "setelah". Tujuan utama dari aspek adalah untuk mendukung masalah lintas sektor, seperti logging, profiling, caching, dan manajemen transaksi.

Dan jika Anda ingin mendalami ekspresi pointcut, lihat pengantar sebelumnya untuk ini.

2. Mengaktifkan Advice

Dengan Spring, Anda dapat mendeklarasikan saran menggunakan anotasi AspectJ, tetapi Anda harus terlebih dahulu menerapkan anotasi @EnableAspectJAutoProxy ke kelas konfigurasi Anda , yang akan mengaktifkan dukungan untuk menangani komponen yang ditandai dengan anotasi @Aspect dari AspectJ .

@Configuration @EnableAspectJAutoProxy public class AopConfiguration { ... }

2.1. Sepatu Musim Semi

Dalam proyek Spring Boot, kami tidak harus menggunakan @EnableAspectJAutoProxy secara eksplisit . Ada AopAutoConfiguration khusus yang mengaktifkan dukungan AOP Spring jika Aspect atau Advice ada di classpath.

3. Sebelum Nasihat

Nasihat ini, seperti namanya, dijalankan sebelum titik penghubung. Itu tidak mencegah kelanjutan eksekusi dari metode yang disarankan kecuali ada pengecualian.

Pertimbangkan aspek berikut yang hanya mencatat nama metode sebelum dipanggil:

@Component @Aspect public class LoggingAspect { private Logger logger = Logger.getLogger(LoggingAspect.class.getName()); @Pointcut("@target(org.springframework.stereotype.Repository)") public void repositoryMethods() {}; @Before("repositoryMethods()") public void logMethodCall(JoinPoint jp) { String methodName = jp.getSignature().getName(); logger.info("Before " + methodName); } }

The logMethodCall saran akan dieksekusi sebelum metode repositori setiap didefinisikan oleh repositoryMethods pointcut.

4. Setelah Nasihat

Setelah saran, dideklarasikan dengan menggunakan anotasi @After , dijalankan setelah eksekusi metode yang cocok, terlepas dari apakah pengecualian dilemparkan atau tidak.

Dalam beberapa hal, ini mirip dengan blok terakhir . Jika Anda memerlukan saran untuk dipicu hanya setelah eksekusi normal, Anda harus menggunakan saran kembali yang dideklarasikan oleh anotasi @AfterReturning . Jika Anda ingin saran Anda dipicu hanya saat metode target melontarkan pengecualian, Anda harus menggunakan saran melempar, yang dideklarasikan dengan menggunakan anotasi @AfterThrowing .

Misalkan kita ingin memberi tahu beberapa komponen aplikasi ketika sebuah instance baru dari Foo dibuat. Kami dapat mempublikasikan acara dari FooDao , tetapi ini akan melanggar prinsip tanggung jawab tunggal.

Sebaliknya, kita dapat melakukannya dengan mendefinisikan aspek berikut:

@Component @Aspect public class PublishingAspect { private ApplicationEventPublisher eventPublisher; @Autowired public void setEventPublisher(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } @Pointcut("@target(org.springframework.stereotype.Repository)") public void repositoryMethods() {} @Pointcut("execution(* *..create*(Long,..))") public void firstLongParamMethods() {} @Pointcut("repositoryMethods() && firstLongParamMethods()") public void entityCreationMethods() {} @AfterReturning(value = "entityCreationMethods()", returning = "entity") public void logMethodCall(JoinPoint jp, Object entity) throws Throwable { eventPublisher.publishEvent(new FooCreationEvent(entity)); } }

Perhatikan, pertama, bahwa dengan menggunakan anotasi eturn @AfterR kita dapat mengakses nilai kembalian metode target. Kedua, dengan mendeklarasikan parameter tipe JoinPoint, kita bisa mengakses argumen pemanggilan metode target.

Selanjutnya kami membuat pendengar yang hanya akan mencatat acara:

@Component public class FooCreationEventListener implements ApplicationListener { private Logger logger = Logger.getLogger(getClass().getName()); @Override public void onApplicationEvent(FooCreationEvent event) { logger.info("Created foo instance: " + event.getSource().toString()); } }

5. Seputar Saran

Di sekitar saran mengelilingi titik gabungan seperti pemanggilan metode.

Ini adalah jenis nasihat yang paling ampuh. Sekitar saran dapat melakukan perilaku kustom sebelum dan sesudah pemanggilan metode. Ini juga bertanggung jawab untuk memilih apakah akan melanjutkan ke titik gabungan atau mempersingkat eksekusi metode yang disarankan dengan memberikan nilai kembaliannya sendiri atau membuat pengecualian.

Untuk mendemonstrasikan penggunaannya, misalkan kita ingin mengukur waktu eksekusi metode. Mari buat Aspek untuk ini:

@Aspect @Component public class PerformanceAspect { private Logger logger = Logger.getLogger(getClass().getName()); @Pointcut("within(@org.springframework.stereotype.Repository *)") public void repositoryClassMethods() {}; @Around("repositoryClassMethods()") public Object measureMethodExecutionTime(ProceedingJoinPoint pjp) throws Throwable { long start = System.nanoTime(); Object retval = pjp.proceed(); long end = System.nanoTime(); String methodName = pjp.getSignature().getName(); logger.info("Execution of " + methodName + " took " + TimeUnit.NANOSECONDS.toMillis(end - start) + " ms"); return retval; } }

Saran ini dipicu ketika salah satu titik gabungan yang cocok dengan pointcut repositoryClassMethods dijalankan.

Saran ini menggunakan satu parameter tipe ProceedingJointPoint . Parameter memberi kita kesempatan untuk mengambil tindakan sebelum pemanggilan metode target. Aku n kasus ini, kita hanya menghemat waktu metode start.

Kedua, tipe pengembalian saran adalah Objek karena metode target dapat mengembalikan hasil dari tipe apa pun. Jika metode target tidak berlaku, null akan dikembalikan. Setelah panggilan metode target, kita dapat mengukur waktu, mencatatnya, dan mengembalikan nilai hasil metode ke pemanggil.

6. Ikhtisar

Dalam artikel ini, kami telah mempelajari berbagai jenis saran di Spring beserta deklarasi dan implementasinya. Kami mendefinisikan aspek menggunakan pendekatan berbasis skema dan menggunakan anotasi AspectJ. Kami juga telah menyediakan beberapa aplikasi saran yang memungkinkan.

Penerapan semua contoh dan cuplikan kode ini dapat ditemukan di proyek GitHub saya.