JavaRush /Java Blog /Random-ID /Apa itu AOP? Dasar-dasar Pemrograman Berorientasi Aspek

Apa itu AOP? Dasar-dasar Pemrograman Berorientasi Aspek

Dipublikasikan di grup Random-ID
Hallo teman-teman! Tanpa memahami konsep dasarnya, cukup sulit untuk mempelajari kerangka kerja dan pendekatan untuk membangun fungsionalitas. Jadi hari ini kita akan membicarakan salah satu konsep ini - AOP, atau pemrograman berorientasi aspek . Apa itu AOP?  Dasar-dasar Pemrograman Berorientasi Aspek - 1Ini bukanlah topik yang mudah dan tidak sering digunakan secara langsung, namun banyak kerangka kerja dan teknologi yang menggunakannya secara tersembunyi. Dan tentu saja, terkadang selama wawancara Anda mungkin diminta untuk memberi tahu Anda secara umum jenis hewan apa itu dan di mana ia dapat digunakan. Jadi mari kita lihat konsep dasar dan beberapa contoh sederhana AOP di Java . Apa itu AOP?  Dasar-dasar Pemrograman Berorientasi Aspek - 2Jadi, AOP - pemrograman berorientasi aspek - adalah paradigma yang bertujuan untuk meningkatkan modularitas berbagai bagian aplikasi dengan memisahkan masalah lintas sektoral. Untuk melakukan hal ini, perilaku tambahan ditambahkan ke kode yang ada, tanpa mengubah kode asli. Dengan kata lain, kita sepertinya menggantungkan fungsionalitas tambahan di atas metode dan kelas tanpa melakukan perubahan pada kode yang dimodifikasi. Mengapa hal ini perlu? Cepat atau lambat kita sampai pada kesimpulan bahwa pendekatan berorientasi objek yang biasa tidak selalu dapat menyelesaikan masalah tertentu secara efektif. Pada saat seperti itu, AOP datang untuk menyelamatkan dan memberi kita alat tambahan untuk membangun aplikasi. Dan alat tambahan berarti peningkatan fleksibilitas dalam pengembangan, sehingga terdapat lebih banyak pilihan untuk memecahkan masalah tertentu.

Penerapan AOP

Pemrograman berorientasi aspek dirancang untuk memecahkan masalah lintas sektoral, yang dapat berupa kode apa pun yang diulang berkali-kali dengan cara berbeda, yang tidak dapat sepenuhnya disusun menjadi modul terpisah. Oleh karena itu, dengan AOP kita dapat membiarkan ini di luar kode utama dan mendefinisikannya secara vertikal. Contohnya adalah penerapan kebijakan keamanan pada suatu aplikasi. Biasanya, keamanan melintasi banyak elemen aplikasi. Selain itu, kebijakan keamanan aplikasi harus diterapkan secara merata pada seluruh bagian aplikasi yang ada dan yang baru. Pada saat yang sama, kebijakan keamanan yang digunakan dapat berkembang dengan sendirinya. Di sinilah penggunaan AOP bisa berguna . Contoh lainnya juga adalah logging . Ada beberapa keuntungan menggunakan pendekatan AOP pada logging dibandingkan memasukkan logging secara manual:
  1. Kode logging mudah diterapkan dan dihapus: Anda hanya perlu menambah atau menghapus beberapa konfigurasi pada beberapa aspek.
  2. Semua kode sumber untuk logging disimpan di satu tempat dan tidak perlu mencari semua tempat penggunaan secara manual.
  3. Kode yang dimaksudkan untuk logging dapat ditambahkan di mana saja, baik itu metode dan kelas yang sudah ditulis atau fungsi baru. Hal ini mengurangi jumlah kesalahan pengembang.
    Selain itu, saat Anda menghapus aspek dari konfigurasi desain, Anda dapat benar-benar yakin bahwa semua kode jejak telah dihapus dan tidak ada yang hilang.
  4. Aspek adalah kode yang berdiri sendiri yang dapat digunakan kembali dan ditingkatkan lagi dan lagi.
Apa itu AOP?  Dasar-dasar Pemrograman Berorientasi Aspek - 3AOP juga digunakan untuk penanganan pengecualian, caching, dan penghapusan beberapa fungsi agar dapat digunakan kembali.

Konsep dasar AOP

Untuk melangkah lebih jauh dalam analisis topik, mari kita kenali dulu konsep utama AOP. Saran adalah logika tambahan, kode, yang dipanggil dari titik koneksi. Saran ini dapat dilakukan sebelum, sesudah, atau sebagai pengganti titik koneksi (lebih lanjut tentangnya di bawah). Jenis saran yang mungkin :
  1. Sebelum (Sebelum) - saran jenis ini diluncurkan sebelum pelaksanaan metode target - titik koneksi. Saat menggunakan aspek sebagai kelas, kami menggunakan anotasi @Before untuk menandai jenis saran sebagai yang datang sebelumnya. Saat menggunakan aspek sebagai file .aj , ini akan menjadi metode before() .
  2. Setelah (Setelah) - saran yang dijalankan setelah selesainya eksekusi metode - titik koneksi, baik dalam kasus normal maupun ketika pengecualian dilemparkan.
    Saat menggunakan aspek sebagai kelas, kita dapat menggunakan anotasi @After untuk menunjukkan bahwa ini adalah tip yang muncul setelahnya.
    Saat menggunakan aspek sebagai file .aj , ini akan menjadi metode after() .
  3. Setelah Kembali - tips ini dijalankan hanya jika metode target bekerja normal, tanpa kesalahan.
    Ketika aspek direpresentasikan sebagai kelas, kita dapat menggunakan anotasi @AfterReturning untuk menandai saran sebagai dieksekusi setelah berhasil diselesaikan.
    Saat menggunakan aspek sebagai file .aj, ini akan menjadi metode after() yang mengembalikan (Object obj) .
  4. After Throwing - saran jenis ini ditujukan untuk kasus-kasus ketika suatu metode, yaitu titik koneksi, memunculkan pengecualian. Kita dapat menggunakan saran ini untuk beberapa penanganan eksekusi yang gagal (misalnya, mengembalikan seluruh transaksi atau mencatat log dengan tingkat jejak yang diperlukan).
    Untuk kelas aspek, anotasi @AfterThrowing digunakan untuk menunjukkan bahwa saran ini digunakan setelah pengecualian dilempar.
    Saat menggunakan aspek dalam bentuk file .aj , ini akan menjadi metode - after() throw (Exception e) .
  5. Sekitar mungkin adalah salah satu jenis saran terpenting yang mengelilingi suatu metode, yaitu titik koneksi, yang dengannya kita dapat, misalnya, memilih apakah akan menjalankan metode titik koneksi tertentu atau tidak.
    Anda dapat menulis kode saran yang dijalankan sebelum dan sesudah metode join point dijalankan.
    Tanggung jawab seputar saran termasuk memanggil metode join point dan mengembalikan nilai jika metode tersebut mengembalikan sesuatu. Artinya, dalam tip ini Anda cukup meniru pengoperasian metode target tanpa memanggilnya, dan sebagai hasilnya, mengembalikan sesuatu milik Anda sendiri.
    Untuk aspek yang berbentuk kelas, kami menggunakan anotasi @Around untuk membuat tips yang membungkus titik koneksi. Saat menggunakan aspek sebagai file .aj , ini akan menjadi metode around() .
Titik gabungan - titik dalam program yang dijalankan (memanggil metode, membuat objek, mengakses variabel) di mana saran harus diterapkan. Dengan kata lain, ini adalah semacam ekspresi reguler, yang dengannya tempat untuk memasukkan kode (tempat untuk menerapkan tip) ditemukan. Pointcut adalah sekumpulan titik koneksi . Pemotongan menentukan apakah titik sambungan tertentu sesuai dengan ujung tertentu. Aspek adalah modul atau kelas yang mengimplementasikan fungsionalitas ujung ke ujung. Sebuah aspek memodifikasi perilaku kode lainnya dengan menerapkan saran pada titik gabungan yang ditentukan oleh beberapa irisan . Dengan kata lain, ini adalah kombinasi tip dan titik koneksi. Pendahuluan - mengubah struktur kelas dan/atau mengubah hierarki warisan untuk menambahkan fungsionalitas aspek ke kode asing. Sasaran adalah obyek dimana nasehat tersebut akan diterapkan. Weaving adalah proses menghubungkan aspek dengan objek lain untuk membuat objek proxy yang direkomendasikan. Hal ini dapat dilakukan pada waktu kompilasi, waktu buka, atau waktu proses. Ada tiga jenis tenun:
  • Tenun waktu kompilasi - Jika Anda memiliki kode sumber suatu aspek dan kode yang menggunakan aspek tersebut, Anda dapat mengkompilasi kode sumber dan aspek secara langsung menggunakan kompiler AspectJ;
  • tenun pasca-kompilasi (tenun biner) - jika Anda tidak bisa atau tidak ingin menggunakan transformasi kode sumber untuk memasukkan aspek ke dalam kode Anda, Anda dapat mengambil kelas atau toples yang sudah dikompilasi dan memasukkan aspek;
  • penenunan waktu muat hanyalah penenunan biner yang ditangguhkan hingga pemuat kelas memuat file kelas dan mendefinisikan kelas untuk JVM.
    Untuk mendukung hal ini, diperlukan satu atau lebih "weave class loader". Mereka secara eksplisit disediakan oleh runtime atau diaktifkan oleh "weaving agent".
AspectJ merupakan implementasi spesifik dari paradigma AOP yang mengimplementasikan kemampuan untuk memecahkan masalah lintas sektoral. Dokumentasi dapat ditemukan di sini .

Contohnya di Jawa

Selanjutnya untuk lebih memahami AOP, kita akan melihat contoh kecil level Hello World. Apa itu AOP?  Dasar-dasar Pemrograman Berorientasi Aspek - 4Izinkan saya segera mencatat bahwa dalam contoh kita, kita akan menggunakan tenun waktu kompilasi . Pertama kita perlu menambahkan ketergantungan berikut ke pom.xml :
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjrt</artifactId>
  <version>1.9.5</version>
</dependency>
Biasanya, kompiler Ajs khusus digunakan untuk menggunakan aspek . IntelliJ IDEA tidak memilikinya secara default, jadi ketika memilihnya sebagai kompiler aplikasi, Anda perlu menentukan jalur ke distribusi AspectJ . Anda dapat membaca lebih lanjut tentang metode memilih Ajs sebagai compiler di halaman ini. Ini adalah metode pertama, dan yang kedua (yang saya gunakan) adalah menambahkan plugin berikut ke pom.xml :
<build>
  <plugins>
     <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <version>1.7</version>
        <configuration>
           <complianceLevel>1.8</complianceLevel>
           <source>1.8</source>
           <target>1.8</target>
           <showWeaveInfo>true</showWeaveInfo>
           <verbose>true</verbose>
           <Xlint>ignore</Xlint>
           <encoding>UTF-8</encoding>
        </configuration>
        <executions>
           <execution>
              <goals>
                 <goal>compile</goal>
                 <goal>test-compile</goal>
              </goals>
           </execution>
        </executions>
     </plugin>
  </plugins>
</build>
Setelah ini, disarankan untuk mengimpor ulang dari Maven dan menjalankan mvn clean kompilasi . Sekarang mari kita beralih ke contohnya.

Contoh No.1

Mari kita buat kelas Utama . Di dalamnya kita akan memiliki titik peluncuran dan metode yang mencetak nama yang diteruskan ke konsol tersebut:
public class Main {

  public static void main(String[] args) {
  printName("Толя");
  printName("Вова");
  printName("Sasha");
  }

  public static void printName(String name) {
     System.out.println(name);
  }
}
Tidak ada yang rumit: mereka meneruskan nama itu dan menampilkannya di konsol. Jika kita menjalankannya sekarang, konsol akan menampilkan:
Tolya Vova Sasha
Nah, inilah saatnya memanfaatkan kekuatan AOP. Sekarang kita perlu membuat file- aspek . Ada dua jenisnya: yang pertama adalah file dengan ekstensi .aj , yang kedua adalah kelas reguler yang mengimplementasikan kemampuan AOP menggunakan anotasi. Pertama mari kita lihat file dengan ekstensi .aj :
public aspect GreetingAspect {

  pointcut greeting() : execution(* Main.printName(..));

  before() : greeting() {
     System.out.print("Привет ");
  }
}
File ini agak mirip dengan kelas. Mari kita cari tahu apa yang terjadi di sini: pointcut - potongan atau sekumpulan titik koneksi; salam() — nama irisan ini; : eksekusi - saat mengeksekusi * - semua, panggil - Main.printName(..) - metode ini. Berikutnya adalah saran khusus - sebelum() - yang dijalankan sebelum metode target dipanggil, : salam() - potongan yang menjadi reaksi saran ini, dan di bawah ini kita melihat isi metode itu sendiri, yang ditulis dalam Java bahasa yang kita pahami. Ketika kita menjalankan main dengan aspek ini, kita akan mendapatkan output berikut ke konsol:
Halo Tolya Halo Vova Halo Sasha
Kita dapat melihat bahwa setiap panggilan ke metode printName telah diubah oleh suatu aspek. Sekarang mari kita lihat seperti apa tampilannya, tetapi sebagai kelas Java dengan anotasi:
@Aspect
public class GreetingAspect{

  @Pointcut("execution(* Main.printName(String))")
  public void greeting() {
  }

  @Before("greeting()")
  public void beforeAdvice() {
     System.out.print("Привет ");
  }
}
Setelah file aspek .aj , semuanya menjadi lebih jelas:
  • @Aspect menunjukkan bahwa kelas yang diberikan adalah sebuah aspek;
  • @Pointcut("execution(* Main.printName(String))") adalah titik potong yang diaktifkan pada semua panggilan ke Main.printName dengan argumen masuk bertipe String ;
  • @Before("greeting()") - saran yang diterapkan sebelum memanggil kode yang dijelaskan pada titik potonggreeting() .
Menjalankan main dengan aspek ini tidak akan mengubah keluaran konsol:
Halo Tolya Halo Vova Halo Sasha

Contoh No.2

Katakanlah kita memiliki beberapa metode yang melakukan beberapa operasi untuk klien dan memanggil metode ini dari main :
public class Main {

  public static void main(String[] args) {
  makeSomeOperation("Толя");
  }

  public static void makeSomeOperation(String clientName) {
     System.out.println("Выполнение некоторых операций для клиента - " + clientName);
  }
}
Dengan menggunakan anotasi @Around , mari lakukan sesuatu seperti “transaksi semu”:
@Aspect
public class TransactionAspect{

  @Pointcut("execution(* Main.makeSomeOperation(String))")
  public void executeOperation() {
  }

  @Around(value = "executeOperation()")
  public void beforeAdvice(ProceedingJoinPoint joinPoint) {
     System.out.println("Открытие транзакции...");
     try {
        joinPoint.proceed();
        System.out.println("Закрытие транзакции....");
     }
     catch (Throwable throwable) {
        System.out.println("Операция не удалась, откат транзакции...");
     }
  }
  }
Dengan menggunakan metode proses dari objek ProceedingJoinPoint , kita memanggil metode pembungkus untuk menentukan tempatnya di papan dan, dengan demikian, kode dalam metode di atas joinPoint.proceed(); - ini Sebelum , yang di bawah - Setelah . Jika kita menjalankan main kita akan mendapatkan di konsol:
Membuka transaksi... Melakukan beberapa operasi untuk klien - Tolya Menutup transaksi....
Jika kita menambahkan pengecualian pada metode kita (tiba-tiba operasi gagal):
public static void makeSomeOperation(String clientName)throws Exception {
  System.out.println("Выполнение некоторых операций для клиента - " + clientName);
  throw new Exception();
}
Kemudian kita akan mendapatkan output di konsol:
Membuka transaksi... Melakukan beberapa operasi untuk klien - Tolya Operasi gagal, transaksi dibatalkan...
Ternyata itu adalah kegagalan pemrosesan semu.

Contoh No.3

Sebagai contoh selanjutnya, mari kita lakukan sesuatu seperti masuk ke konsol. Pertama, mari kita lihat Main , tempat logika bisnis semu kita terjadi:
public class Main {
  private String value;

  public static void main(String[] args) throws Exception {
     Main main = new Main();
     main.setValue("<некоторое meaning>");
     String valueForCheck = main.getValue();
     main.checkValue(valueForCheck);
  }

  public void setValue(String value) {
     this.value = value;
  }

  public String getValue() {
     return this.value;
  }

  public void checkValue(String value) throws Exception {
     if (value.length() > 10) {
        throw new Exception();
     }
  }
}
Di main , menggunakan setValue, kita akan menetapkan nilai variabel internal - value , kemudian menggunakan getValue, kita akan mengambil nilai ini dan di checkValue kita akan memeriksa apakah nilai ini lebih panjang dari 10 karakter. Jika ya, pengecualian akan diberikan. Sekarang mari kita lihat aspek yang akan digunakan untuk mencatat pengoperasian metode:
@Aspect
public class LogAspect {

  @Pointcut("execution(* *(..))")
  public void methodExecuting() {
  }

  @AfterReturning(value = "methodExecuting()", returning = "returningValue")
  public void recordSuccessfulExecution(JoinPoint joinPoint, Object returningValue) {
     if (returningValue != null) {
        System.out.printf("Успешно выполнен метод - %s, класса- %s, с результатом выполнения - %s\n",
              joinPoint.getSignature().getName(),
              joinPoint.getSourceLocation().getWithinType().getName(),
              returningValue);
     }
     else {
        System.out.printf("Успешно выполнен метод - %s, класса- %s\n",
              joinPoint.getSignature().getName(),
              joinPoint.getSourceLocation().getWithinType().getName());
     }
  }

  @AfterThrowing(value = "methodExecuting()", throwing = "exception")
  public void recordFailedExecution(JoinPoint joinPoint, Exception exception) {
     System.out.printf("Метод - %s, класса- %s, был аварийно завершен с исключением - %s\n",
           joinPoint.getSignature().getName(),
           joinPoint.getSourceLocation().getWithinType().getName(),
           exception);
  }
}
Apa yang terjadi di sini? @Pointcut("execution(* *(..))") - akan terhubung ke semua panggilan ke semua metode; @AfterReturning(value = "methodExecuting()", return = "returningValue") - saran yang akan dieksekusi setelah metode target berhasil diselesaikan. Kami memiliki dua kasus di sini:
  1. Ketika suatu metode memiliki nilai kembalian if (returningValue != null) {
  2. Ketika tidak ada nilai kembalian yang lain {
@AfterThrowing(value = "methodExecuting()", throw = "Exception") - saran yang akan dipicu jika terjadi kesalahan, yaitu ketika pengecualian dilemparkan dari metode. Dan karenanya, dengan menjalankan main , kita akan mendapatkan semacam logging di konsol:
Metode - setValue, dari kelas - Utama berhasil dieksekusi Metode - getValue, dari kelas - Utama, berhasil dieksekusi, dengan hasil eksekusi - <beberapa nilai> Metode - checkValue, dari kelas - Utama, dihentikan secara tidak normal dengan pengecualian - Metode java.lang.Exception - utama, kelas-Utama, mogok dengan pengecualian - java.lang.Exception
Nah, karena kami tidak menangani pengecualian tersebut, kami juga akan mendapatkan pelacakan tumpukannya: Apa itu AOP?  Dasar-dasar Pemrograman Berorientasi Aspek - 5Anda dapat membaca tentang pengecualian dan penanganannya di artikel ini: Pengecualian di Java dan Pengecualian serta penanganannya . Itu saja untukku hari ini. Hari ini kita berkenalan dengan AOP , dan Anda dapat melihat bahwa binatang ini tidak seseram yang dilukis. Selamat tinggal semuanya!Apa itu AOP?  Dasar-dasar Pemrograman Berorientasi Aspek - 6
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION