Pengenalan kepada AspectJ

1. Pengenalan

Artikel ini adalah pengenalan pantas dan praktikal untuk AspectJ.

Pertama, kami akan menunjukkan cara mengaktifkan pengaturcaraan berorientasikan aspek, dan kemudian kami akan memfokus pada perbezaan antara tenunan masa kompilasi, pasca kompilasi, dan tenunan waktu muat.

Mari kita mulakan dengan pengenalan ringkas pengaturcaraan berorientasikan aspek (AOP) dan asas AspectJ.

2. Gambaran keseluruhan

AOP adalah paradigma pengaturcaraan yang bertujuan untuk meningkatkan modulariti dengan membenarkan pemisahan masalah silang. Ia melakukannya dengan menambahkan tingkah laku tambahan pada kod yang ada tanpa mengubah kod itu sendiri. Sebaliknya, kami menyatakan secara berasingan kod mana yang hendak diubah.

AspectJ mengimplementasikan kedua-dua keprihatinan dan penenunan keprihatinan silang menggunakan peluasan bahasa pengaturcaraan Java.

3. Pergantungan Maven

AspectJ menawarkan perpustakaan yang berbeza bergantung pada penggunaannya. Kita dapat mencari pergantungan Maven di bawah kumpulan org.aspectj di repositori Maven Central.

Dalam artikel ini, kami memfokuskan pada kebergantungan yang diperlukan untuk membuat aspek dan Weaver menggunakan Tenun kompilasi, pasca kompilasi, dan waktu muat.

3.1. Masa Jalan AspectJ

Semasa menjalankan program AspectJ, classpath harus mengandungi kelas dan aspek bersama dengan AspectJ runtime library aspekjrt.jar :

 org.aspectj aspectjrt 1.8.9 

Pergantungan ini terdapat di Maven Central.

3.2. AspekJWeaver

Selain kebergantungan runtime AspectJ, kami juga perlu memasukkan aspekjweaver.jar untuk memperkenalkan nasihat ke kelas Java pada waktu muat:

 org.aspectj aspectjweaver 1.8.9 

Ketergantungan juga terdapat di Maven Central.

4. Penciptaan Aspek

AspectJ menyediakan pelaksanaan AOP dan mempunyai tiga konsep teras:

  • Sertailah Point
  • Titik titik
  • Nasihat

Kami akan menunjukkan konsep ini dengan membuat program mudah untuk mengesahkan baki akaun pengguna.

Pertama, mari buat kelas Akaun dengan baki yang diberikan dan kaedah untuk mengeluarkan:

public class Account { int balance = 20; public boolean withdraw(int amount) { if (balance < amount) { return false; } balance = balance - amount; return true; } }

Kami akan membuat fail AccountAspect.aj untuk log maklumat akaun dan mengesahkan baki akaun (perhatikan bahawa fail AspectJ diakhiri dengan pelanjutan fail " .aj "):

public aspect AccountAspect { final int MIN_BALANCE = 10; pointcut callWithDraw(int amount, Account acc) : call(boolean Account.withdraw(int)) && args(amount) && target(acc); before(int amount, Account acc) : callWithDraw(amount, acc) { } boolean around(int amount, Account acc) : callWithDraw(amount, acc) { if (acc.balance < amount) { return false; } return proceed(amount, acc); } after(int amount, Account balance) : callWithDraw(amount, balance) { } }

Seperti yang dapat kita lihat, kita telah menambahkan potongan titik ke kaedah penarikan dan membuat tiga nasihat yang merujuk kepada titik titik yang ditentukan .

Untuk memahami perkara berikut, kami memperkenalkan definisi berikut:

  • Aspek : Modulasi keprihatinan yang melintasi pelbagai objek. Setiap aspek menumpukan pada fungsi potong silang tertentu
  • Titik bergabung : Titik selama pelaksanaan skrip, seperti pelaksanaan metode atau akses harta benda
  • Nasihat : Tindakan yang diambil oleh aspek pada titik bergabung tertentu
  • Titik Titik : Ungkapan biasa yang sepadan dengan titik bergabung. Nasihat dikaitkan dengan ungkapan titik dan berjalan di mana-mana titik gabungan yang sepadan dengan potongan titik

Untuk keterangan lebih lanjut mengenai konsep ini dan semantik khusus mereka, kami mungkin ingin melihat pautan berikut.

Seterusnya, kita perlu memasukkan aspek ke dalam kod kita. Bahagian di bawah membahas tiga jenis tenunan: tenunan waktu kompilasi, tenun pasca kompilasi, dan tenunan masa muat di AspectJ.

5. Tenunan Masa Kompilasi

Pendekatan tenunan yang paling mudah adalah tenunan waktu kompilasi. Apabila kita mempunyai kod sumber aspek dan kod yang kita gunakan aspek, penyusun AspectJ akan menyusun dari sumber dan menghasilkan fail kelas tenunan sebagai output. Setelah itu, setelah pelaksanaan kod anda, kelas output proses tenunan dimuat ke dalam JVM sebagai kelas Java biasa.

Kita boleh memuat turun Alat Pembangunan AspectJ kerana ia merangkumi penyusun AspectJ yang dibundel. Salah satu ciri AJDT yang paling penting adalah alat untuk memvisualisasikan kebimbangan rentas jalan, yang berguna untuk menyahpepijat spesifikasi titik potong. Kami mungkin memvisualisasikan kesan gabungan bahkan sebelum kod digunakan.

Kami menggunakan Plugin Mojo's AspectJ Maven untuk menenun aspek AspectJ ke dalam kelas kami menggunakan penyusun AspectJ.

 org.codehaus.mojo aspectj-maven-plugin 1.7  1.8 1.8 1.8 true true ignore UTF-8       compile  test-compile    

Untuk keterangan lebih lanjut mengenai rujukan pilihan penyusun AspectJ, kami mungkin ingin melihat pautan berikut.

Mari tambahkan beberapa kes ujian untuk kelas Akaun kami:

public class AccountTest { private Account account; @Before public void before() { account = new Account(); } @Test public void given20AndMin10_whenWithdraw5_thenSuccess() { assertTrue(account.withdraw(5)); } @Test public void given20AndMin10_whenWithdraw100_thenFail() { assertFalse(account.withdraw(100)); } }

Semasa kami menjalankan kes ujian, teks di bawah yang ditunjukkan di konsol bermaksud bahawa kami berjaya menenun kod sumber:

[INFO] Join point 'method-call (boolean com.baeldung.aspectj.Account.withdraw(int))' in Type 'com.baeldung.aspectj.test.AccountTest' (AccountTest.java:20) advised by around advice from 'com.baeldung.aspectj.AccountAspect' (AccountAspect.class:18(from AccountAspect.aj)) [INFO] Join point 'method-call (boolean com.baeldung.aspectj.Account.withdraw(int))' in Type 'com.baeldung.aspectj.test.AccountTest' (AccountTest.java:20) advised by before advice from 'com.baeldung.aspectj.AccountAspect' (AccountAspect.class:13(from AccountAspect.aj)) [INFO] Join point 'method-call (boolean com.baeldung.aspectj.Account.withdraw(int))' in Type 'com.baeldung.aspectj.test.AccountTest' (AccountTest.java:20) advised by after advice from 'com.baeldung.aspectj.AccountAspect' (AccountAspect.class:26(from AccountAspect.aj)) 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Balance before withdrawal: 20 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Withdraw ammout: 5 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Balance after withdrawal : 15 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Balance before withdrawal: 20 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Withdraw ammout: 100 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Withdrawal Rejected! 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - Balance after withdrawal : 20

6. Tenunan Pasca Kompilasi

Tenunan pasca-kompilasi (juga kadang-kadang disebut tenunan binari) digunakan untuk menenun fail kelas dan fail JAR yang ada. Seperti tenunan waktu kompilasi, aspek yang digunakan untuk menenun mungkin dalam bentuk sumber atau binari, dan mungkin sendiri ditenun oleh aspek.

Untuk melakukan ini dengan Mojo's AspectJ Maven Plugin, kita perlu menyediakan semua fail JAR yang ingin kita tenun dalam konfigurasi pemalam:

   org.agroup to-weave   org.anothergroup gen   

The JAR files containing the classes to weave must be listed as in the Maven project and listed as in the of the AspectJ Maven Plugin.

7. Load-Time Weaving

Load-time weaving is simply binary weaving deferred until the point that a class loader loads a class file and defines the class to the JVM.

To support this, one or more “weaving class loaders” are required. These are either provided explicitly by the run-time environment or enabled using a “weaving agent”.

7.1. Enabling Load-Time Weaving

AspectJ load-time weaving can be enabled using AspectJ agent that can get involved in the class loading process and weave any types before they are defined in the VM. We specify the javaagent option to the JVM -javaagent:pathto/aspectjweaver.jar or using Maven plugin to configure the javaagent :

 org.apache.maven.plugins maven-surefire-plugin 2.10   -javaagent:"${settings.localRepository}"/org/aspectj/ aspectjweaver/${aspectj.version}/ aspectjweaver-${aspectj.version}.jar  true always  

7.2. Configuration Weaver

AspectJ's load-time weaving agent is configured by the use of aop.xml files. It looks for one or more aop.xml files on the classpath in the META-INF directory and aggregates the contents to determine the weaver configuration.

An aop.xml file contains two key sections:

  • Aspects: defines one or more aspects to the weaver and controls which aspects are to be used in the weaving process. The aspects element may optionally contain one or more include and exclude elements (by default, all defined aspects are used for weaving)
  • Weaver: defines weaver options to the weaver and specifies the set of types that should be woven. If no include elements are specified then all types visible to the weaver will be woven

Let's configure an aspect to the weaver:

As we can see, we have configured an aspect that points to the AccountAspect, and only the source code in the com.baeldung.aspectj package will be woven by AspectJ.

8. Annotating Aspects

In addition to the familiar AspectJ code-based style of aspect declaration, AspectJ 5 also supports an annotation-based style of aspect declaration. We informally call the set of annotations that support this development style the “@AspectJ” annotations.

Let's create an annotation:

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Secured { public boolean isLocked() default false; }

We use the @Secured annotation to enable or disable a method:

public class SecuredMethod { @Secured(isLocked = true) public void lockedMethod() { } @Secured(isLocked = false) public void unlockedMethod() { } }

Next, we add an aspect using AspectJ annotation-style, and check the permission based on the attribute of the @Secured annotation:

@Aspect public class SecuredMethodAspect { @Pointcut("@annotation(secured)") public void callAt(Secured secured) { } @Around("callAt(secured)") public Object around(ProceedingJoinPoint pjp, Secured secured) throws Throwable { return secured.isLocked() ? null : pjp.proceed(); } }

For more detail on AspectJ annotation-style, we can check out the following link.

Next, we weave our class and aspect using load-time weaver and put aop.xml under META-INF folder:

Finally, we add unit test and check the result:

@Test public void testMethod() throws Exception { SecuredMethod service = new SecuredMethod(); service.unlockedMethod(); service.lockedMethod(); }

Semasa menjalankan kes ujian, kami mungkin memeriksa output konsol untuk mengesahkan bahawa kami berjaya menenun aspek dan kelas kami dalam kod sumber:

[INFO] Join point 'method-call (void com.baeldung.aspectj.SecuredMethod.unlockedMethod())' in Type 'com.baeldung.aspectj.test.SecuredMethodTest' (SecuredMethodTest.java:11) advised by around advice from 'com.baeldung.aspectj.SecuredMethodAspect' (SecuredMethodAspect.class(from SecuredMethodAspect.java)) 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.SecuredMethod - unlockedMethod 2016-11-15 22:53:51 [main] INFO c.b.aspectj.SecuredMethodAspect - public void com.baeldung.aspectj.SecuredMethod.lockedMethod() is locked

9. Kesimpulannya

Dalam artikel ini, kami membahas konsep pengenalan mengenai AspectJ. Untuk perincian, anda boleh melihat halaman utama AspectJ.

Anda boleh mendapatkan kod sumber untuk artikel ini di GitHub.