Aplikasi AOP
Pemrograman berorientasi aspek dirancang kanggo nindakake tugas nglereni, sing bisa dadi kode apa wae sing bisa diulang kaping pirang-pirang kanthi cara sing beda-beda, sing ora bisa ditata kanthi lengkap dadi modul sing kapisah. Mulane, AOP ngidini kita nyimpen iki ing njaba kode utama lan nyatakake kanthi vertikal. Conto nggunakake kabijakan keamanan ing aplikasi. Biasane, keamanan mbukak liwat akeh unsur aplikasi. Kajaba iku, kabijakan keamanan aplikasi kudu ditrapake kanthi padha kanggo kabeh bagean aplikasi sing wis ana lan anyar. Ing wektu sing padha, kabijakan keamanan sing digunakake bisa berkembang dhewe. Iki minangka papan sing cocog kanggo nggunakake AOP . Uga, conto liyane yaiku logging. Ana sawetara kaluwihan kanggo nggunakake pendekatan AOP kanggo logging tinimbang nambahake fungsi logging kanthi manual:-
Kode kanggo logging gampang ditambahake lan dibusak: sampeyan mung kudu nambah utawa mbusak sawetara konfigurasi saka sawetara aspek.
-
Kabeh kode sumber kanggo logging disimpen ing sak panggonan, dadi sampeyan ora perlu kanthi manual mburu kabeh panggonan sing digunakake.
-
Kode logging bisa ditambahake ing ngendi wae, ing metode lan kelas sing wis ditulis utawa ing fungsi anyar. Iki nyuda jumlah kesalahan coding.
Uga, nalika mbusak aspek saka konfigurasi desain, sampeyan bisa yakin manawa kabeh kode tilak wis ilang lan ora ana sing kejawab.
- Aspek minangka kode kapisah sing bisa ditambah lan digunakake maneh lan maneh.
Prinsip dhasar AOP
Kanggo luwih maju ing topik iki, ayo ngerti konsep utama AOP. Saran - Logika tambahan utawa kode sing diarani saka titik gabungan. Saran bisa ditindakake sadurunge, sawise, utawa tinimbang titik gabung (liyane babagan ing ngisor iki). Jenis saran sing bisa :-
Sadurunge — saran jinis iki diluncurake sadurunge metode target, yaiku gabung poin, dieksekusi. Nalika nggunakake aspek minangka kelas, kita nggunakake anotasi @Before kanggo menehi tandha saran minangka sadurunge. Nalika nggunakake aspèk minangka file .aj , iki bakal sadurunge () cara.
- Sawise - saran sing dileksanakake sawise eksekusi cara (titik gabung) rampung, loro ing eksekusi normal uga nalika mbuwang pangecualian.
Nalika nggunakake aspèk minangka kelas, kita bisa nggunakake @After anotasi kanggo nunjukaké sing iki saran sing teka sawise.
Nalika nggunakake aspèk minangka file .aj , iki sawise () cara.
-
Sawise Returning — saran iki dileksanakake mung nalika cara target rampung normal, tanpa kasalahan.
Nalika aspek dituduhake minangka kelas, kita bisa nggunakake anotasi @AfterReturning kanggo menehi tandha saran minangka eksekusi sawise rampung sukses.
Nalika nggunakake aspèk minangka file .aj , iki bakal sawise () cara bali (Obyek obj) .
-
Sawise Mbuwang — saran iki dimaksudaké kanggo kedadean nalika cara, sing, gabung titik, mbalang pangecualian. Kita bisa nggunakake saran iki kanggo nangani jinis eksekusi gagal tartamtu (contone, kanggo mbalekake kabeh transaksi utawa log kanthi tingkat tilak sing dibutuhake).
Kanggo aspek kelas, anotasi @AfterThrowing digunakake kanggo nunjukake yen saran iki digunakake sawise mbuwang pengecualian.
Nalika nggunakake aspèk minangka file .aj , iki bakal sawise () cara mbuwang (Istiméwa e) .
-
Around - mbok menawa salah siji saka jinis paling penting saka saran. Iku ngubengi cara, yaiku, titik gabung sing bisa digunakake, contone, milih arep nindakake metode titik gabung utawa ora.
Sampeyan bisa nulis kode saran sing mlaku sadurunge lan sawise metode titik gabung dieksekusi.
Saran watara tanggung jawab kanggo nelpon cara titik gabung lan nilai bali yen cara ngasilake soko. Ing tembung liyane, ing saran iki, sampeyan mung bisa simulasi operasi saka cara target tanpa nelpon, lan bali apa wae sing dikarepake minangka asil bali.
Diwenehi aspek minangka kelas, kita nggunakake @Around anotasi kanggo nggawe saran sing mbungkus titik gabung. Nalika nggunakake aspèk ing wangun file .aj , cara iki bakal watara () cara.
-
Compile-time weaving — yen sampeyan duwe kode sumber aspek lan kode ing ngendi sampeyan nggunakake aspek kasebut, sampeyan bisa ngumpulake kode sumber lan aspek kasebut langsung nggunakake kompiler AspectJ;
-
Post-compile weaving (biner weaving) - yen sampeyan ora bisa utawa ora pengin nggunakake transformasi kode sumber kanggo nenun aspèk menyang kode, sampeyan bisa njupuk kelas sadurunge nyawiji utawa file jar lan inject aspèk menyang wong;
-
Load-time weaving — iki mung binar weaving sing ditundha nganti classloader mbukak file kelas lan nemtokake kelas kanggo JVM.
Siji utawa luwih loader kelas tenun dibutuhake kanggo ndhukung iki. Lagi salah siji tegas diwenehake dening runtime utawa diaktifake dening "agen weaving."
Tuladha ing basa Jawa
Sabanjure, kanggo luwih ngerti AOP , kita bakal katon ing cilik "Hello World" -gaya conto. Tengen saka bat, aku bakal nyathet yen conto kita bakal nggunakake tenun wektu kompilasi . Kaping pisanan, kita kudu nambah dependensi ing ngisor iki ing file pom.xml :
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.5</version>
</dependency>
Minangka aturan, compiler ajc khusus yaiku carane nggunakake aspek. IntelliJ IDEA ora kalebu minangka standar, supaya nalika milih minangka compiler aplikasi, sampeyan kudu nemtokake path menyang distribusi 5168 75 AspectJ . Iki minangka cara pisanan. Kapindho, sing digunakake, yaiku ndhaptar plugin ing ngisor iki ing file 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>
Sawise iki, luwih becik ngimpor maneh saka Maven lan mbukak mvn clean compile . Saiki ayo nerusake langsung menyang conto.
Tuladha No. 1
Ayo nggawe kelas Utama . Ing kono, kita bakal duwe titik entri lan cara sing nyithak jeneng sing dilewati ing konsol:
public class Main {
public static void main(String[] args) {
printName("Tanner");
printName("Victor");
printName("Sasha");
}
public static void printName(String name) {
System.out.println(name);
}
}
Ora ana sing rumit ing kene. We liwati jeneng lan nampilake ing console. Yen kita mbukak program saiki, kita bakal weruh ing ngisor iki ing console:
public aspect GreetingAspect {
pointcut greeting() : execution(* Main.printName(..));
before() : greeting() {
System.out.print("Hi, ");
}
}
File iki kaya kelas. Ayo ndeleng apa sing kedadeyan ing kene: pointcut minangka set titik gabungan; salam () iku jeneng pointcut iki; : eksekusi nuduhake kanggo aplikasi sak eksekusi kabeh ( * ) telpon saka Main.printName (...) cara. Sabanjure ana saran tartamtu - sadurunge () - sing dieksekusi sadurunge metode target diarani. : salam () minangka titik potong sing ditanggepi saran iki. Inggih, ing ngandhap punika kawontênakên badanipun tata cara piyambak, ingkang kaserat mawi basa Jawi, ingkang dipun mangrêtosi. Nalika kita mbukak utama kanthi aspek iki, kita bakal entuk output konsol iki:
@Aspect
public class GreetingAspect{
@Pointcut("execution(* Main.printName(String))")
public void greeting() {
}
@Before("greeting()")
public void beforeAdvice() {
System.out.print("Hi, ");
}
}
Sawise file aspek .aj , kabeh dadi luwih jelas ing kene:
- @Aspect nuduhake yen kelas iki minangka aspek;
- @Pointcut("execution(* Main.printName(String))") iku cutpoint sing dipicu kanggo kabeh panggilan menyang Main.printName kanthi argumen input sing jinis String ;
- @Before ("salam ()") minangka saran sing ditrapake sadurunge nelpon kode kasebut ing titik potong salam () .
Tuladha No. 2
Upaminipun kita duwe sawetara cara sing nindakake sawetara operasi kanggo klien, lan kita nelpon cara iki saka utama :
public class Main {
public static void main(String[] args) {
performSomeOperation("Tanner");
}
public static void performSomeOperation(String clientName) {
System.out.println("Performing some operations for Client " + clientName);
}
}
Ayo gunakake anotasi @Around kanggo nggawe "pseudo-transaction":
@Aspect
public class TransactionAspect{
@Pointcut("execution(* Main.performSomeOperation(String))")
public void executeOperation() {
}
@Around(value = "executeOperation()")
public void beforeAdvice(ProceedingJoinPoint joinPoint) {
System.out.println("Opening a transaction...");
try {
joinPoint.proceed();
System.out.println("Closing a transaction...");
}
catch (Throwable throwable) {
System.out.println("The operation failed. Rolling back the transaction...");
}
}
}
Kanthi cara nerusake obyek ProceedingJoinPoint , kita nelpon cara bungkus kanggo nemtokake lokasi ing saran. Mulane, kode ing cara ndhuwur joinPoint.proceed (); yaiku Sadurunge , dene kode ing ngisor iki yaiku Sawise . Yen kita mbukak main , kita entuk iki ing console:
public static void performSomeOperation(String clientName) throws Exception {
System.out.println("Performing some operations for Client " + clientName);
throw new Exception();
}
Banjur kita entuk output konsol iki:
Tuladha No. 3
Ing conto sabanjure, ayo nglakoni kaya mlebu menyang konsol. Pisanan, deleng Main , ing ngendi kita wis nambah sawetara logika bisnis pseudo:
public class Main {
private String value;
public static void main(String[] args) throws Exception {
Main main = new Main();
main.setValue("<some value>");
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();
}
}
}
Ing utama , kita nggunakake setValue kanggo nemtokake nilai kanggo variabel conto nilai . Banjur kita nggunakake getValue kanggo entuk nilai, banjur nelpon checkValue kanggo ndeleng yen luwih saka 10 karakter. Yen mangkono, pangecualian bakal dibuwang. Saiki ayo goleki aspek sing bakal digunakake kanggo log karya 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("Successful execution: method — %s method, class — %s class, return value — %s\n",
joinPoint.getSignature().getName(),
joinPoint.getSourceLocation().getWithinType().getName(),
returningValue);
}
else {
System.out.printf("Successful execution: method — %s, class — %s\n",
joinPoint.getSignature().getName(),
joinPoint.getSourceLocation().getWithinType().getName());
}
}
@AfterThrowing(value = "methodExecuting()", throwing = "exception")
public void recordFailedExecution(JoinPoint joinPoint, Exception exception) {
System.out.printf("Exception thrown: method — %s, class — %s, exception — %s\n",
joinPoint.getSignature().getName(),
joinPoint.getSourceLocation().getWithinType().getName(),
exception);
}
}
Apa sing kedadeyan ing kene? @Pointcut("eksekusi(* *(..))") bakal nggabungake kabeh panggilan kabeh cara. @AfterReturning(value = "methodExecuting()", returning = "returningValue") iku saran sing bakal dileksanakake sawise kasil eksekusi metode target. Kita duwe rong kasus ing kene:
- Nalika metode kasebut nduweni nilai bali - yen (returningValue! = Null) {
- Nalika ora ana nilai bali - liya {
GO TO FULL VERSION