מבוא ל- AspectJ

1. הקדמה

מאמר זה הוא מבוא מהיר ופרקטי ל- AspectJ.

ראשית, נראה כיצד לאפשר תכנות מונחה-היבט, ואז נתמקד בהבדל בין זמן הידור, פוסט-קומפילציה ואריגת זמן טעינה.

נתחיל בהקדמה קצרה של תכנות מונחה-היבט (AOP) והיסודות של AspectJ.

2. סקירה כללית

AOP היא פרדיגמת תכנות שמטרתה להגביר את המודולריות על ידי מתן הפרדה בין חששות רוחביים. היא עושה זאת על ידי הוספת התנהגות נוספת לקוד הקיים ללא שינוי הקוד עצמו. במקום זאת, אנו מצהירים בנפרד איזה קוד יש לשנות.

AspectJ מיישמת הן את החששות והן את השזירה של חששות רוחביים באמצעות הרחבות של שפת התכנות Java.

3. תלות Maven

AspectJ מציעה ספריות שונות בהתאם לשימוש בה. אנו יכולים למצוא תלות של Maven תחת קבוצת org.aspectj במאגר Maven Central.

במאמר זה אנו מתמקדים בתלות הדרושה ליצירת היבטים וב- Weaver תוך שימוש ב- Weavers בזמן הידור, פוסט-קומפילציה וזמן טעינה.

3.1. זמן ריצה של AspectJ

בעת הפעלת תוכנית AspectJ, על מסלול הכיתה להכיל את הכיתות וההיבטים יחד עם ספריית זמן הריצה של AspectJ aspectjrt.jar:

 org.aspectj aspectjrt 1.8.9 

תלות זו זמינה ב- Maven Central.

3.2. AspectJWeaver

מלבד התלות של זמן הריצה של AspectJ, נצטרך לכלול את ה- aspectjweaver.jar להציג ייעוץ לשיעור Java בזמן הטעינה:

 org.aspectj aspectjweaver 1.8.9 

התלות זמינה גם ב- Maven Central.

4. יצירת היבט

AspectJ מספק יישום של AOP ויש לו שלושה מושגי ליבה:

  • הצטרף לנקודה
  • פוינטקאט
  • עֵצָה

נדגים מושגים אלה על ידי יצירת תוכנית פשוטה לאימות יתרה בחשבון המשתמש.

ראשית, בואו ניצור חֶשְׁבּוֹן כיתה עם יתרה נתונה ושיטה למשוך:

חשבון בכיתה ציבורית {יתרת int = 20; משיכה בוליאנית ציבורית (סכום int) {אם (יתרה <סכום) {החזר כוזב; } יתרה = יתרה - סכום; לחזור אמיתי; }}

ניצור AccountAspect.aj קובץ לרישום פרטי חשבון וכדי לאמת את היתרה בחשבון (שים לב שקבצי AspectJ מסתיימים בסימן ".aj" סיומת קובץ):

היבט ציבורי AccountAspect {final int MIN_BALANCE = 10; pointcut callWithDraw (סכום int, חשבון חשבון): call (חשבון בוליאני. עם משיכה (int)) && args (סכום) && target (acc); לפני (סכום int, חשבון acc): callWithDraw (סכום, acc) {} בוליאני מסביב (סכום int, חשבון acc): callWithDraw (סכום, acc) {אם (acc. יתרה <סכום) {return false; } החזר המשך (סכום, acc); } אחרי (סכום int, יתרת חשבון): callWithDraw (סכום, יתרה) {}}

כפי שאנו רואים, הוספנו א קיצור דרך לשיטת הנסיגה ויצר שלוש מייעץ המתייחסים להגדרה קיצור דרך.

על מנת להבין את הדברים הבאים, אנו מציגים את ההגדרות הבאות:

  • אספקט: מודולריזציה של דאגה החוצה אובייקטים מרובים. כל היבט מתמקד בפונקציונליות חיתוך ספציפית
  • נקודת הצטרפות: נקודה במהלך ביצוע סקריפט, כגון ביצוע שיטה או גישה לנכס
  • עֵצָה: פעולה המבוצעת על ידי היבט בנקודת הצטרפות מסוימת
  • פוינטקאט: ביטוי קבוע התואם נקודות הצטרפות. עצה קשורה לביטוי קיצורי דרך ורצה בכל נקודת צירוף שתואמת את קיצור הדרך

לפרטים נוספים על מושגים אלה והסמנטיקה הספציפית שלהם, ייתכן שנרצה לבדוק את הקישור הבא.

לאחר מכן, עלינו לשזור את ההיבטים בקוד שלנו. החלקים שלהלן מתייחסים לשלושה סוגים שונים של אריגה: אריגה בזמן הידור, אריגה לאחר הידור ואריגה בזמן עומס ב- AspectJ.

5. אריגה בזמן קומפילציה

הגישה הפשוטה ביותר של אריגה היא אריגה בזמן הידור. כשיש לנו גם את קוד המקור של ההיבט וגם את הקוד שאנו משתמשים בהיבטים, המהדר AspectJ ילקט מהמקור וייצור קבצי מחלקה ארוגים כפלט. לאחר מכן, עם ביצוע הקוד שלך, מחלקת הפלט של תהליך האריגה נטענת ב- JVM כמעמד Java רגיל.

אנו יכולים להוריד את כלי הפיתוח של AspectJ מכיוון שהוא כולל מהדר AspectJ יחד. אחד המאפיינים החשובים ביותר של AJDT הוא כלי להדמיה של חששות רוחביים, אשר מועיל לניפוי באגים במפרט קיצורי דרך. אנו עשויים לדמיין את האפקט המשולב עוד לפני פריסת הקוד.

אנו משתמשים בתוסף AspectJ Maven של Mojo כדי לשזור את ההיבטים של AspectJ לשיעורים שלנו באמצעות מהדר AspectJ.

 org.codehaus.mojo aspectj-maven-plugin 1.7 1.8 1.8 1.8 נכון להתעלם UTF-8 הידור מבחן קומפילציה 

לפרטים נוספים על הפניה לאופציה של מהדר AspectJ, כדאי שנבדוק את הקישור הבא.

בואו נוסיף כמה מקרי מבחן בכיתת החשבון שלנו:

ClassTest AccountTest {חשבון פרטי פרטי; @ לפני בטל הציבור לפני () {חשבון = חשבון חדש (); } @Test ציבורי בטל נתון 20AndMin10_whenWithdraw5_thenSuccess () {assertTrue (account.withdraw (5)); } @Test הציבור בטל שניתן20AndMin10_whenWithdraw100_thenFail () {assertFalse (account.withdraw (100)); }}

כאשר אנו מריצים את מקרי הבדיקה, הטקסט שלמטה המוצג במסוף פירושו שארגנו בהצלחה את קוד המקור:

[INFO] הצטרף לנקודה 'שיטת קריאה (בוליאנית com.baeldung.aspectj.Account.withdraw (int))' בסוג 'com.baeldung.aspectj.test.AccountTest' (AccountTest.java:20) המומלצת על ידי עצות סביב 'com.baeldung.aspectj.AccountAspect' (AccountAspect.class: 18 (מ- AccountAspect.aj)) [INFO] הצטרפות נקודת שיטה נקודה (com.baeldung.aspectj.Account.withdraw (int)) בוליאני בסוג ' com.baeldung.aspectj.test.AccountTest '(AccountTest.java:20) מומלץ לפני ייעוץ מ- com.baeldung.aspectj.AccountAspect' (AccountAspect.class: 13 (מ- AccountAspect.aj)) [INFO] נקודת הצטרפות ' שיטת שיחה (בוליאנית com.baeldung.aspectj.Account.withdraw (int)) 'בסוג' com.baeldung.aspectj.test.AccountTest '(AccountTest.java:20) המומלצת על ידי ייעוץ מאת' com.baeldung.aspectj .AccountAspect '(AccountAspect.class: 26 (from AccountAspect.aj)) 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - יתרה לפני משיכה: 20 2016-11-15 22: 53:51 [ראשי] INFO com.baeldung.aspectj.AccountAspect - נסיגה ammout: 5 2016 -11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - יתרה לאחר נסיגה: 15 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - איזון לפני נסיגה: 20 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - משוך ammout: 100 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.AccountAspect - נסיגה נדחתה! 2016-11-15 22:53:51 [ראשי] INFO com.baeldung.aspectj.AccountAspect - יתרה לאחר נסיגה: 20

6. אריגה לאחר קומפילציה

אריגה לאחר הידור (המכונה לעתים גם אריגה בינארית) משמשת לארוג קבצי מחלקה וקבצי JAR קיימים. בדומה לאריגה בזמן הידור, ההיבטים המשמשים לאריגה עשויים להיות בצורת מקור או בינארי, והם עשויים להיות ארוגים על ידי היבטים.

על מנת לעשות זאת עם תוסף AspectJ Maven של Mojo עלינו להתקין את כל קבצי ה- JAR שנרצה לשזור בתצורת התוסף:

   org.agroup to-weave org.anothergroup gen 

יש לרשום את קבצי ה- JAR המכילים את הכיתות לשזור בפרויקט Maven ורשום כ בתוך ה של תוסף AspectJ Maven.

7. אריגת זמן טעינה

אריגת זמן טעינה היא פשוט דחייה של אריגה בינארית עד לנקודה שמעמיס מחלקה טוען קובץ מחלקה ומגדיר את הכיתה ל- JVM.

כדי לתמוך בכך, נדרש אחד או יותר "מעמיסי כיתת אריגה". אלה מסופקים באופן מפורש על ידי סביבת זמן הריצה או מופעלים באמצעות "סוכן אריגה".

7.1. הפעלת אריגת זמן טעינה

ניתן להפעיל את אריגת זמן הטעינה של AspectJ באמצעות סוכן AspectJ שיכול להיות מעורב בתהליך הטעינה בכיתה ולשזור כל סוג לפני שהוא מוגדר ב- VM. אנו מציינים את javaagent אפשרות ל- JVM -javaagent: pathto / aspectjweaver.jar או באמצעות תוסף Maven להגדרת התצורה של javaagent :

 org.apache.maven.plugins maven-surefire-plugin 2.10 -javaagent: "$ {settings.localRepository}" / org / aspectj / aspectjweaver / $ {aspectj.version} / aspectjweaver - $ {aspectj.version} .jar נכון תמיד 

7.2. תצורת ויבר

סוכן האריגה של AspectJ מוגדר על ידי שימוש ב- aop.xml קבצים. זה מחפש אחד או יותר aop.xml קבצים בשביל הכיתה META-INF מדריך ומאגד את התוכן כדי לקבוע את תצורת האורג.

An aop.xml הקובץ מכיל שני קטעי מפתח:

  • היבטים: מגדיר היבט אחד או יותר בפני האורג ושולט באילו היבטים יש להשתמש בתהליך האריגה. ה היבטים אלמנט יכול לכלול אפשרות אחת או יותר לִכלוֹל ו לא לכלול אלמנטים (כברירת מחדל, כל ההיבטים המוגדרים משמשים לאריגה)
  • אוֹרֵג: מגדיר את האריגה לאורג ומציין את קבוצת הסוגים שיש לארוג. אם לא צוינו אלמנטים כלולים, כל הסוגים הגלויים לאורגים יירקמו

בואו להגדיר היבט לאורג:

כפי שאנו רואים, הגדרנו היבט שמצביע על ה- AccountAspect, ורק קוד המקור ב- com.baeldung.aspectj החבילה תארוג על ידי AspectJ.

8. היבטים ביאורים

בנוסף לסגנון AspectJ המוכר על בסיס קוד של הכרזת היבט, AspectJ 5 תומך גם בסגנון מבוסס ההערה של הצהרת היבט. אנו קוראים באופן לא רשמי למכלול ההערות התומכות בסגנון התפתחות זה "@AspectJביאורים.

בואו ליצור הערה:

@Retention (RetentionPolicy.RUNTIME) @Target (ElementType.METHOD) public @interface מאובטח {ברירת מחדל בוליאנית isLocked () שקר; }

אנו משתמשים ב- @מְאוּבטָח ביאור להפעלה או השבתה של שיטה:

מחלקה ציבורית SecuredMethod {@Secured (isLocked = true) public void lockedMethod () {} @Secured (isLocked = false) public public unlockedMethod () {}}

לאחר מכן, אנו מוסיפים היבט באמצעות סגנון ההערה של AspectJ, ונבדוק את ההרשאה על סמך התכונה של ההערה @Secured:

@Aspect מחלקה ציבורית SecuredMethodAspect {@Pointcut ("@ ביאור (מאובטח)") בטל ציבורי בטל (מאובטח מאובטח) {} @Around ("callAt (מאובטח)") אובייקט ציבורי מסביב (המשך JooinPoint pjp, מאובטח מאובטח) זורק זורק secure.isLocked ()? null: pjp.proceed (); }}

לפרטים נוספים על סגנון ההערות של AspectJ, נוכל לבדוק את הקישור הבא.

לאחר מכן, אנו שוזרים את המעמד וההיבט שלנו באמצעות שוזר זמן וטעינה aop.xml תַחַת META-INF תיקיה:

לבסוף, אנו מוסיפים בדיקת יחידה ובודקים את התוצאה:

@Test ציבורי בטל testMethod () זורק חריג {שירות SecuredMethod = SecuredMethod חדש (); service.unlockedMethod (); service.lockedMethod (); }

כאשר אנו מריצים את מקרי הבדיקה, אנו עשויים לבדוק את פלט המסוף כדי לוודא שקילענו בהצלחה את ההיבט והמחלקה שלנו בקוד המקור:

] com.baeldung.aspectj.SecuredMethodAspect '(SecuredMethodAspect.class (מתוך SecuredMethodAspect.java)) 2016-11-15 22:53:51 [main] INFO com.baeldung.aspectj.SecuredMethod - unlockedMethod 2016-11-15 22:53 : 51 [ראשי] INFO cbaspectj.SecuredMethodAspect - חלל ציבורי com.baeldung.aspectj.SecuredMethod.lockedMethod () נעול

9. מסקנה

במאמר זה סקרנו מושגי היכרות בנושא AspectJ. לפרטים תוכלו לעיין בדף הבית של AspectJ.

אתה יכול למצוא את קוד המקור של מאמר זה ב- GitHub.