AOP لاڳو ڪرڻ
Aspect-oriented programming ٺهيل آهي ڪراس ڪٽنگ ڪمن کي انجام ڏيڻ لاءِ، جيڪو ڪو به ڪوڊ ٿي سگهي ٿو جيڪو مختلف طريقن سان ڪيترائي ڀيرا ورجائي سگهجي ٿو، جنهن کي مڪمل طور تي الڳ ماڊل ۾ ترتيب نه ٿو ڏئي سگهجي. ان جي مطابق، AOP اسان کي هن کي مکيه ڪوڊ کان ٻاهر رکڻ جي اجازت ڏئي ٿو ۽ ان کي عمودي طور تي اعلان ڪري ٿو. هڪ مثال هڪ ايپليڪيشن ۾ سيڪيورٽي پاليسي استعمال ڪري رهيو آهي. عام طور تي، سيڪيورٽي ايپليڪيشن جي ڪيترن ئي عناصر ذريعي هلندو آهي. وڌيڪ ڇا آهي، ايپليڪيشن جي سيڪيورٽي پاليسي کي لاڳو ڪيو وڃي هڪجهڙائي سان ايپليڪيشن جي سڀني موجوده ۽ نئين حصن تي. ساڳئي وقت، استعمال ۾ هڪ سيڪيورٽي پاليسي پاڻ کي ترقي ڪري سگهي ٿو. هي AOP استعمال ڪرڻ لاءِ بهترين جڳهه آهي . پڻ، ٻيو مثال لاگنگ آهي . لاگنگ لاءِ AOP طريقي کي استعمال ڪرڻ جا ڪيترائي فائدا آھن بجاءِ دستي طور تي لاگنگ فنڪشنل شامل ڪرڻ جي.-
لاگنگ لاءِ ڪوڊ شامل ڪرڻ ۽ ختم ڪرڻ آسان آھي: توھان کي بس ڪرڻ جي ضرورت آھي شامل ڪرڻ يا ختم ڪرڻ لاءِ ڪجھ ڪنفيگريشنز جو ڪجھ پاسو.
-
لاگنگ لاءِ سڀ سورس ڪوڊ هڪ جاءِ تي رکيل آهي، تنهنڪري توهان کي دستي طور تي انهن سڀني هنڌن کي ڳولڻ جي ضرورت ناهي جتي اهو استعمال ڪيو ويو آهي.
-
لاگنگ ڪوڊ ڪٿي به شامل ڪري سگھجي ٿو، ڇا طريقن ۽ طبقن ۾ جيڪي اڳ ۾ ئي لکيل آھن يا نئين ڪارڪردگي ۾. هي ڪوڊنگ جي غلطين جو تعداد گھٽائي ٿو.
انهي سان گڏ، جڏهن ڊزائن جي جوڙجڪ مان هڪ پاسو کي هٽائڻ، توهان پڪ ڪري سگهو ٿا ته سڀ ٽريڪنگ ڪوڊ هليو ويو آهي ۽ ڪجهه به نه وڃايو ويو آهي.
- پہلو الڳ الڳ ڪوڊ آھن جيڪي بھتر ڪري سگھجن ٿا ۽ بار بار استعمال ڪري سگھجن ٿا.
AOP جا بنيادي اصول
هن موضوع ۾ اڳتي وڌڻ لاء، اچو ته پهرين AOP جي بنيادي مفهومن کي ڄاڻون. صلاح - اضافي منطق يا ڪوڊ شامل ٿيڻ واري نقطي کان سڏيو وڃي ٿو. مشوري کان اڳ، بعد ۾، يا شامل ٿيڻ واري پوائنٽ جي بدران ٿي سگھي ٿو (انهن بابت وڌيڪ ھيٺ ڏنل). نصيحت جا ممڪن قسم :-
اڳ - ھن قسم جي صلاح ھدف جي طريقن، يعني جوائن پوائنٽس، تي عمل ٿيڻ کان اڳ شروع ڪئي ويندي آھي. جڏهن پهلوئن کي ڪلاس طور استعمال ڪريون ٿا، اسان استعمال ڪريون ٿا @Before تشريح کي نشان ھڻڻ لاءِ جيئن اڳي اچڻ. جڏهن .aj فائلن جي طور تي پہلو استعمال ڪندي، اهو اڳوڻو () طريقو هوندو .
- بعد ۾ - مشورو جيڪو عمل ڪرڻ کان پوءِ عمل ڪيو وڃي ٿو طريقن (جوائن پوائنٽس) مڪمل ٿي چڪو آهي، ٻئي عام عمل ۾ ۽ گڏوگڏ هڪ استثنا اڇلائڻ ۾.
جڏهن پهلوئن کي طبقن جي طور تي استعمال ڪيو وڃي، اسان استعمال ڪري سگهون ٿا @After تشريح ظاهر ڪرڻ لاءِ ته اهو مشورو آهي جيڪو بعد ۾ اچي ٿو.
جڏهن .aj فائلن جي طور تي پہلو استعمال ڪندي ، هي آهي after() طريقو.
-
موٽڻ کان پوءِ - هي مشورو صرف تڏهن ڪيو ويندو آهي جڏهن ٽارگيٽ جو طريقو عام طور تي ختم ٿئي، بغير ڪنهن غلطي جي.
جڏهن پهلوئن کي طبقن جي طور تي پيش ڪيو وڃي، اسان استعمال ڪري سگھون ٿا @AfterReturning annotation کي نشان ھڻڻ لاءِ مشوري کي ڪامياب مڪمل ٿيڻ کان پوءِ عمل ڪرڻ.
جڏهن .aj فائلن جي طور تي پہلو استعمال ڪندي ، اهو ٿيندو after() موٽڻ (Object obj) طريقو.
-
اڇلائڻ کان پوءِ - هي صلاح ان مثالن لاءِ آهي جڏهن هڪ طريقو، اهو آهي، جوائن پوائنٽ، هڪ استثنا اڇلائي ٿو. اسان ھي صلاح استعمال ڪري سگھون ٿا ڪجھ قسم جي ناڪامي جي عمل کي سنڀالڻ لاءِ (مثال طور، ھڪڙي مڪمل ٽرانزيڪشن کي واپس ڪرڻ يا گھربل ٽريس ليول سان لاگ ان ڪرڻ).
طبقاتي پهلوئن لاءِ، @AfterThrowing annotation استعمال ڪيو ويندو آهي اهو ظاهر ڪرڻ لاءِ ته هي مشورو استعمال ڪيو ويندو آهي استثنا اڇلائڻ کان پوءِ.
جڏهن .aj فائلن جي طور تي پہلو استعمال ڪندي ، اهو ٿيندو after() اڇلائڻ (Exception e) طريقو.
-
چوڌاري - شايد مشوري جي سڀ کان اهم قسمن مان هڪ. اهو هڪ طريقي جي چوڌاري گهيرو ڪري ٿو، اهو آهي، هڪ شامل ٿيڻ واري نقطي جنهن کي اسين استعمال ڪري سگهون ٿا، مثال طور، چونڊيو ته ڏنل شامل ٿيڻ واري پوائنٽ جو طريقو انجام ڏيڻ يا نه.
توھان لکي سگھوٿا مشوري ڪوڊ جيڪو ھلندو آھي ان کان اڳ ۽ پوءِ جوائن پوائنٽ جو طريقو عمل ۾ اچي ٿو.
چوڌاري مشوري جوائنٽ پوائنٽ جي طريقي کي ڪال ڪرڻ ۽ واپسي جي قيمتن جي ذميوار آھي جيڪڏھن طريقو ڪجھھ موٽائي ٿو. ٻين لفظن ۾، هن مشوري ۾، توهان صرف ان کي سڏڻ کان سواء ٽارگيٽ طريقي جي آپريشن کي نقل ڪري سگهو ٿا، ۽ واپسي جي نتيجي ۾ جيڪو توهان چاهيو ٿا واپس ڪري سگهو ٿا.
ڪلاس جي طور تي ڏنل پهلو، اسان استعمال ڪندا آهيون @Around تشريح مشوري ٺاهڻ لاءِ جيڪا شامل ٿيڻ واري نقطي کي لپي ٿي. جڏهن .aj فائلن جي صورت ۾ پهلون کي استعمال ڪندي ، اهو طريقو چوڌاري () طريقو هوندو .
-
Compile-time weaving - جيڪڏھن توھان وٽ آھي اسپيڪٽ جو سورس ڪوڊ ۽ اھو ڪوڊ جتي توھان اسپيڪٽ استعمال ڪندا آھيو، ته پوءِ توھان سڌو سنئون AspectJ ڪمپيلر استعمال ڪندي سورس ڪوڊ ۽ اسپيڪٽ کي گڏ ڪري سگھو ٿا؛
-
پوسٽ-ڪپائل ويلنگ (بائنري ويونگ) - جيڪڏهن توهان ڪوڊ ۾ پهلوئن کي ويو ڪرڻ لاءِ سورس ڪوڊ ٽرانسفارميشن استعمال نٿا ڪري سگهو يا نٿا چاهيو، ته توهان اڳ ۾ مرتب ڪيل ڪلاس يا جار فائل وٺي سگهو ٿا ۽ انهن ۾ پهلوئن کي داخل ڪري سگهو ٿا؛
-
لوڊ ٽائم ويئنگ - ھي صرف بائنري ويونگ آھي جيڪا دير ٿيندي آھي جيستائين ڪلاس لوڊ ڪندڙ ڪلاس فائل لوڊ ڪري ۽ JVM لاءِ ڪلاس جي وضاحت ڪري.
ان کي سپورٽ ڪرڻ لاءِ هڪ يا وڌيڪ ويونگ ڪلاس لوڊرز گهربل آهن. اهي يا ته واضح طور تي رن ٽائم پاران مهيا ڪيا ويا آهن يا "ويونگ ايجنٽ" پاران چالو ڪيا ويا آهن.
جاوا ۾ مثال
اڳيون، AOP جي بهتر سمجھڻ لاءِ ، اسان ڏسنداسين ننڍڙا ”هيلو ورلڊ“ طرز جا مثال. بٽ جي ساڄي، مان نوٽ ڪندس ته اسان جا مثال compile-time weaving استعمال ڪندا . پهرين، اسان کي اسان جي pom.xml فائل ۾ هيٺين انحصار شامل ڪرڻ جي ضرورت آهي :
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.5</version>
</dependency>
ضابطي جي طور تي، خاص ajc ڪمپلر اهو آهي ته اسان ڪئين استعمال ڪندا آهيون. IntelliJ IDEA ان کي ڊفالٽ ۾ شامل نٿو ڪري، تنهنڪري جڏهن ان کي ايپليڪيشن ڪمپلر طور چونڊيو وڃي، توهان کي 5168 75 AspectJ تقسيم جو رستو بيان ڪرڻ گهرجي. اهو پهريون طريقو هو. ٻيو، جيڪو مون استعمال ڪيو آهي، اهو آهي 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>
ان کان پوء، اهو هڪ سٺو خيال آهي ته Maven
کان ٻيهر درآمد ڪرڻ ۽ هلائڻ لاء mvn clean compile . هاڻي اچو ته سڌو سنئون مثالن ڏانهن وڃو.
مثال نمبر 1
اچو ته هڪ مکيه ڪلاس ٺاهي. ان ۾، اسان وٽ ھڪڙو داخلا پوائنٽ ۽ ھڪڙو طريقو آھي جيڪو کنسول تي منظور ٿيل نالو پرنٽ ڪري ٿو:
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);
}
}
هتي ڪجھ به پيچيده ناهي. اسان ھڪڙو نالو پاس ڪيو ۽ ان کي ڪنسول تي ڏيکاريو. جيڪڏهن اسان هاڻي پروگرام هلون ٿا، اسان هيٺ ڏنل ڪنسول تي ڏسندا سين:
public aspect GreetingAspect {
pointcut greeting() : execution(* Main.printName(..));
before() : greeting() {
System.out.print("Hi, ");
}
}
ھي فائل ھڪڙي طبقي وانگر آھي. اچو ته ڏسون هتي ڇا ٿي رهيو آهي: پوائنٽ ڪٽ جوائن پوائنٽس جو هڪ سيٽ آهي. greeting() هن پوائنٽ کٽ جو نالو آهي؛ : execution اشارو ڪري ٿو ته ان کي لاڳو ڪرڻ دوران سڀني ( * ) ڪالن جي عمل جي دوران Main.printName(...) طريقي سان. اڳيون ھڪڙو خاص مشورو اچي ٿو - اڳ () - جيڪو ھدف جو طريقو سڏڻ کان اڳ عمل ڪيو ويو آھي. : greeting() اهو ڪٽ پوائنٽ آهي جنهن جو هي مشورو جواب ڏئي ٿو. خير، ۽ هيٺ اسان طريقي جو جسم ڏسون ٿا، جيڪو جاوا ٻولي ۾ لکيو ويو آهي، جيڪو اسان سمجهون ٿا. جڏهن اسان هن پاسو موجود سان مکيه هلون ٿا ، اسان هي ڪنسول حاصل ڪنداسين:
@Aspect
public class GreetingAspect{
@Pointcut("execution(* Main.printName(String))")
public void greeting() {
}
@Before("greeting()")
public void beforeAdvice() {
System.out.print("Hi, ");
}
}
.aj اسپيڪٽ فائل کان پوء ، هر شيء هتي وڌيڪ واضح ٿي ويندي آهي:
- @ Aspect اشارو ڪري ٿو ته هي طبقو هڪ پاسو آهي؛
- @Pointcut("execution(* Main.printName(String))") اهو ڪٽ پوائنٽ آهي جيڪو Main.printName ڏانهن سڀني ڪالن لاءِ ان پٽ آرگيومينٽ سان ٽرگر ڪيو ويندو آهي جنهن جو قسم آهي String ؛
- @Before("greeting()") مشوري آھي جيڪا ڪال ڪرڻ کان اڳ لاڳو ڪئي ويندي آھي greeting() cutpoint ۾ بيان ڪيل ڪوڊ .
مثال نمبر 2
فرض ڪريو اسان وٽ ھڪڙو طريقو آھي جيڪو ڪجھھ عملن کي انجام ڏئي ٿو گراهڪن لاء، ۽ اسين ھن طريقي کي سڏين ٿا مکيه مان :
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);
}
}
اچو ته استعمال ڪريون @Around تشريح هڪ "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...");
}
}
}
ProceedingJoinPoint اعتراض جي اڳتي وڌڻ واري طريقي سان ، اسان صلاح ۾ ان جي جڳھ کي طئي ڪرڻ لاء لپڻ جو طريقو سڏين ٿا. تنهن ڪري، مٿي ڏنل طريقي ۾ ڪوڊ joinPoint.proceed(); اڳي آهي ، جڏهن ته هيٺ ڏنل ڪوڊ بعد ۾ آهي . جيڪڏهن اسان هلائيندا آهيون main ، اسان هن کي ڪنسول ۾ حاصل ڪندا آهيون:
public static void performSomeOperation(String clientName) throws Exception {
System.out.println("Performing some operations for Client " + clientName);
throw new Exception();
}
پوء اسان هن ڪنسول جي پيداوار حاصل ڪندا آهيون:
مثال نمبر 3
اسان جي ايندڙ مثال ۾، اچو ته ڪنسول کي لاگ ان ڪرڻ وانگر ڪجهه ڪريون. پهرين، هڪ نظر وٺو Main ، جتي اسان شامل ڪيو آهي ڪجهه pseudo business logic:
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();
}
}
}
مکيه ۾ ، اسان setValue استعمال ڪريون ٿا قدر تفويض ڪرڻ لاءِ قدر مثال متغير کي. پوءِ اسان قدر حاصل ڪرڻ لاءِ getValue استعمال ڪريون ٿا، ۽ پوءِ ڏسون ٿا checkValue اهو ڏسڻ لاءِ ته اهو 10 اکرن کان ڊگهو آهي. جيڪڏهن ائين آهي، ته پوء هڪ استثنا اڇلايو ويندو. هاڻي اچو ته ان پاسو تي نظر وجهون جنهن کي اسين استعمال ڪنداسين طريقن جي ڪم کي لاگ ان ڪرڻ لاءِ:
@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);
}
}
هتي ڇا ٿي رهيو آهي؟ @Pointcut("execution(**(..))") سڀني طريقن جي سڀني ڪالن ۾ شامل ٿيندو. @AfterReturning(value = "methodExecuting()", returning = "returningValue") اها صلاح آهي جيڪا ٽارگيٽ جي طريقي جي ڪامياب ٿيڻ کان پوءِ ڪئي ويندي. اسان وٽ هتي ٻه ڪيس آهن:
- جڏهن طريقي ۾ واپسي جي قيمت آهي - جيڪڏهن (returningValue! = Null) {
- جڏهن واپسي جي قيمت نه آهي - ٻيو {
GO TO FULL VERSION