CDI Interceptor לעומת Spring AspectJ

1. הקדמה

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

במאמר זה נסקור ולהבדיל בין שתי ספריות עיקריות אלה: יירוט CDI ו- Spring AspectJ.

2. הגדרת פרויקט יירוט CDI

CDI נתמך באופן רשמי עבור ג'קרטה EE אך חלק מהיישומים מספקים תמיכה לשימוש ב- CDI בסביבת Java SE. ריתוך יכול להיחשב כדוגמה אחת ליישום CDI הנתמך ב- Java SE.

על מנת להשתמש ב- CDI עלינו לייבא את ספריית הריתוך ל- POM שלנו:

 org.jboss.weld.se weld-se-core 3.0.5.Final 

את ספריית ה- Weld האחרונה ניתן למצוא במאגר Maven.

בואו ניצור מיירט פשוט.

3. הכנסת המיירט CDI

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

@InterceptorBinding @Target ({METHOD, TYPE}) @ Retention (RUNTIME) ציבור @ ממשק מבוקר {}

לאחר שהגדרנו את מחייב המיירט עלינו להגדיר את יישום המיירט בפועל:

@ Audit @ Interceptor מחלקה ציבורית AuditedInterceptor {בוליאני סטטי ציבורי בשםBefore = false; בוליאני סטטי ציבורי בשם After = false; @AroundInvoke audit ObjectMethod ציבורי (InvocationContext ctx) זורק Exception {calledBefore = true; תוצאת אובייקט = ctx.proceed (); calledAfter = נכון; תוצאת החזרה; }}

כֹּל @AroundInvoke השיטה לוקחת א javax.interceptor.InvocationContext טיעון, מחזיר א java.lang. אובייקט, ויכול לזרוק יוצא מן הכלל.

וכך, כאשר אנו מציינים שיטה עם החדשה @בְּדִיקָה מִמְשָׁק, auditMethod יופעל תחילה, ורק אז שיטת היעד תמשיך גם כן.

4. החל את ה- CDI Interceptor

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

מעמד ציבורי SuperService {@ מחרוזת ציבורית מבוקרת deliverService (מחרוזת uid) {להחזיר uid; }}

יצרנו את השירות הפשוט הזה והערנו את השיטה שרצינו ליירט עם @Audited ביאור.

כדי לאפשר מיירט CDI צריך לציין את שם המחלקה המלא ב- שעועית.קסמל הקובץ, הממוקם ב META-INF מַדרִיך:

  com.baeldung.interceptor.AuditedInterceptor 

לאמת אותו מיירט אכן עבד בואו נעבור את המבחן הבא:

מחלקה ציבורית TestInterceptor {ריתוך ריתוך; מיכל WeldContainer; @ לפני init בטל פומבי () {weld = ריתוך חדש (); מיכל = weld.initialize (); } @ לאחר כיבוי בטל פומבי () {weld.shutdown (); } @Test הציבור בטל שניתןTheService_whenMethodAndInterceptorExecuted_thenOK () {SuperService superService = container.select (SuperService.class) .get (); קוד מחרוזת = "123456"; superService.deliverService (קוד); Assert.assertTrue (AuditedInterceptor.calledBefore); Assert.assertTrue (AuditedInterceptor.calledAfter); }}

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

כמו כן יש לנו @לפני ו @לאחר שיטות ביאור בהן אנו מאתחלים ומכבים את מיכל הריתוך בהתאמה.

5. שיקולי CDI

אנו יכולים להצביע על היתרונות הבאים של מיירטים CDI:

  • זוהי תכונה סטנדרטית של מפרט EE של ג'קרטה
  • ניתן להשתמש בחלק מספריות הטמעת ה- CDI ב- Java SE
  • ניתן להשתמש כאשר לפרויקט שלנו יש מגבלות חמורות בספריות צד שלישי

החסרונות של מיירט CDI הם אלה:

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

6. היבט האביב J

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

ראשית עלינו להוסיף את תלות האביב וה- AspectJ הבאה ל- POM:

 org.springframework spring-context 5.2.8.RELEASE org.aspectj aspectjweaver 1.9.2 

הגרסאות האחרונות של הקשר האביב, aspectjweaver ניתן למצוא במאגר Maven.

כעת אנו יכולים ליצור היבט פשוט באמצעות תחביר ההערות של AspectJ:

@Aspect מחלקה ציבורית SpringTestAspect {@ מצבר רשימות פרטיות מוסמכות; @Around ("ביצוע (* com.baeldung.spring.service.SpringSuperService. * (..))") ביקורת אובייקט ציבורית (Methode ProceedingJoinPoint jp) זורק {String methodName = jp.getSignature () לזריק (). GetName (); accumulator.add ("התקשר אל" + methodName); אובייקט obj = jp.proceed (); accumulator.add ("השיטה נקראת בהצלחה:" + methodName); החזר אובייקט; }}

יצרנו היבט המתאים לכל השיטות של SpringSuperService בכיתה - שנראה, לפשטות, כך:

מחלקה ציבורית SpringSuperService {public String getInfoFromService (קוד מחרוזת) {קוד החזרה; }}

7. היבט האביב J Aspect החל

על מנת לאמת היבט זה אכן חל על השירות, בוא נכתוב את מבחן היחידה הבא:

@RunWith (SpringRunner.class) @ContextConfiguration (classes = {AppConfig.class}) מחלקה ציבורית TestSpringInterceptor {@Autowired SpringSuperService springSuperService; @ מצבר רשימות פרטיות אוטומטיות; @Test ציבורי בטל givenService_whenServiceAndAspectExecuted_thenOk () {קוד מחרוזת = "123456"; תוצאת מחרוזת = springSuperService.getInfoFromService (קוד); Assert.assertThat (accumulator.size (), הוא (2)); Assert.assertThat (accumulator.get (0), הוא ("התקשר ל- getInfoFromService")); Assert.assertThat (accumulator.get (1), הוא ("השיטה נקראת בהצלחה: getInfoFromService")); }}

בבדיקה זו אנו מזריקים את השירות שלנו, מתקשרים לשיטה ובודקים את התוצאה.

כך נראית התצורה:

@Configuration @EnableAspectJAutoProxy מחלקה ציבורית AppConfig {@Bean הציבור SpringSuperService springSuperService () {להחזיר SpringSuperService חדש (); } @Bean ציבורי SpringTestAspect springTestAspect () {להחזיר SpringTestAspect חדש (); } @Bean הרשימה הציבורית getAccumulator () {החזר ArrayList חדש (); }}

היבט אחד חשוב כאן ב @EnableAspectJAutoProxy ביאור - המאפשר תמיכה בטיפול ברכיבים המסומנים ב- AspectJ @אספקט ביאור, בדומה לפונקציונליות שנמצאת באלמנט ה- XML ​​של Spring.

8. שיקולי האביב של האביב

בואו נציין כמה מהיתרונות של שימוש באביב AspectJ:

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

וכמובן כמה חסרונות:

  • אתה צריך לדעת את התחביר של AspectJ כדי לפתח מיירטים
  • עקומת הלמידה למיירטים של AspectJ גבוהה יותר מאשר למיירטים של ה- CDI

9. CDI Interceptor לעומת Spring AspectJ

אם הפרויקט הנוכחי שלך משתמש באביב, אז בחינת אביב AspectJ היא בחירה טובה.

אם אתה משתמש בשרת יישומים מלא, או שהפרויקט שלך אינו משתמש באביב (או מסגרות אחרות כגון Google Guice) והוא בהחלט ג'קרטה EE, לא נותר אלא לבחור במיירט CDI.

10. מסקנה

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

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


$config[zx-auto] not found$config[zx-overlay] not found