Pengenalan Jenis Nasihat pada Musim Bunga

1. Gambaran keseluruhan

Dalam artikel ini, kita akan membincangkan pelbagai jenis nasihat AOP yang boleh dibuat pada musim bunga.

Nasihat adalah tindakan yang diambil oleh aspek pada titik bergabung tertentu. Berbagai jenis nasihat termasuk nasihat "sekitar", "sebelum" dan "setelah". Tujuan utama aspek adalah untuk menyokong keprihatinan silang, seperti pembalakan, pembuatan profil, penyimpanan cache, dan pengurusan transaksi.

Dan jika anda ingin melihat lebih mendalam ungkapan titik, periksa pengenalan sebelumnya.

2. Mengaktifkan Nasihat

Dengan Spring, anda boleh menyatakan nasihat menggunakan anotasi AspectJ, tetapi anda mesti terlebih dahulu menerapkan anotasi @EnableAspectJAutoProxy ke kelas konfigurasi anda , yang akan membolehkan sokongan untuk mengendalikan komponen yang ditandai dengan anotasi @Aspect AspectJ .

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

2.1. Spring Boot

Dalam projek Spring Boot, kita tidak perlu menggunakan @EnableAspectJAutoProxy secara eksplisit . Terdapat AopAutoConfiguration khusus yang membolehkan sokongan AOP Spring jika Aspek atau Nasihat ada di lorong kelas.

3. Sebelum Nasihat

Nasihat ini, seperti namanya, dilaksanakan sebelum titik bergabung. Ini tidak menghalang pelaksanaan kaedah yang disarankannya kecuali pengecualian dilemparkan.

Pertimbangkan aspek berikut yang hanya mencatat nama kaedah 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); } }

Nasihat logMethodCall akan dilaksanakan sebelum kaedah repositori ditentukan oleh titik titik repositori .

4. Selepas Nasihat

Setelah mendapat nasihat, dinyatakan dengan menggunakan penjelasan @Setelah dilaksanakan, dilaksanakan setelah pelaksanaan metode yang sesuai, terlepas dari pengecualian atau tidak.

Dalam beberapa cara, ia serupa dengan blok akhirnya . Sekiranya anda memerlukan nasihat untuk dicetuskan hanya setelah pelaksanaan normal, anda harus menggunakan nasihat pengembalian yang dinyatakan oleh @AfterReturning anotasi. Sekiranya anda mahukan nasihat anda dicetuskan hanya ketika kaedah sasaran membuang pengecualian, anda harus menggunakan nasihat lemparan, yang dinyatakan dengan menggunakan anotasi @AfterThrowing .

Anggaplah kita ingin memberitahu beberapa komponen aplikasi ketika kejadian baru Foo dibuat. Kami boleh menerbitkan acara dari FooDao , tetapi ini akan melanggar prinsip tanggungjawab tunggal.

Sebagai gantinya, kita dapat menyelesaikannya dengan menentukan 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, bahawa dengan menggunakan anotasi @AfterR eturning kita dapat mengakses nilai kembali kaedah sasaran. Kedua, dengan menyatakan parameter tipe JoinPoint, kita dapat mengakses argumen pemanggilan metode sasaran.

Seterusnya 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. Sekitar Nasihat

Di sekitar nasihat mengelilingi titik bergabung seperti kaedah memohon.

Ini adalah jenis nasihat yang paling kuat. Nasihat di sekitar dapat melakukan tingkah laku tersuai sebelum dan selepas kaedah memohon. Ini juga bertanggung jawab untuk memilih sama ada untuk meneruskan ke titik bergabung atau memotong jalan pelaksanaan kaedah yang disarankan dengan memberikan nilai pengembalian sendiri atau membuang pengecualian.

Untuk menunjukkan penggunaannya, anggaplah bahawa kita ingin mengukur masa pelaksanaan kaedah. 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; } }

Nasihat ini dipicu ketika mana-mana titik gabungan yang dipadankan dengan titik titik repositoriClassMethods dijalankan.

Nasihat ini mengambil satu parameter jenis ProceedingJointPoint . Parameter ini memberi kita kesempatan untuk mengambil tindakan sebelum panggilan metode sasaran. Saya n kes ini, kita hanya menjimatkan masa kaedah permulaan.

Kedua, jenis pengembalian nasihat adalah Objek kerana kaedah sasaran dapat mengembalikan hasil dari jenis apa pun. Sekiranya kaedah sasaran tidak sah, nol akan dikembalikan. Selepas panggilan kaedah sasaran, kita dapat mengukur waktunya, mencatatnya, dan mengembalikan nilai hasil kaedah tersebut kepada pemanggil.

6. Gambaran keseluruhan

Dalam artikel ini, kami telah mengetahui pelbagai jenis nasihat pada musim bunga dan pernyataan serta pelaksanaannya. Kami menentukan aspek menggunakan pendekatan berasaskan skema dan menggunakan anotasi AspectJ. Kami juga telah memberikan beberapa aplikasi nasihat yang mungkin.

Pelaksanaan semua contoh dan coretan kod ini terdapat di projek GitHub saya.