היקף מותאם אישית באביב

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

מהקופסה, אביב מספק שני טווחי שעועית סטנדרטיים ("קְלָף בּוֹדֵד" ו "אב טיפוס") שניתן להשתמש בהם בכל יישום אביב, בתוספת שלושה טווחי שעועית נוספים ("בַּקָשָׁה", "מוֹשָׁב", ו "GlobalSession") לשימוש רק ביישומים מודעים לאינטרנט.

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

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

במדריך מהיר זה נדגים כיצד ליצור, לרשום ולהשתמש בהיקף מותאם אישית ביישום Spring.

2. יצירת מחלקת היקף מותאמת אישית

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

2.1. ניהול האובייקטים וההתקשרות חוזרת

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

עבור מאמר זה, נעשה זאת בצורה חוטה באמצעות מפות מסונכרנות.

נתחיל להגדיר את מחלקת ההיקף המותאמת אישית שלנו:

מחלקה ציבורית TenantScope מיישמת Scope {Map private scopedObjects = Collections.synchronizedMap (חדש HashMap ()); מפה פרטית destroyCallbacks = Collections.synchronizedMap (HashMap חדש ()); ...}

2.2. אחזור אובייקט מההיקף

כדי לאחזר אובייקט לפי השם מההיקף שלנו, בואו נשתמש ב- getObject שיטה. כפי שקובע JavaDoc, אם האובייקט ששמו אינו קיים בהיקף, שיטה זו חייבת ליצור ולהחזיר אובייקט חדש.

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

@Override אובייקט ציבורי get (שם מחרוזת, ObjectFactory objectFactory) {אם (! ScopedObjects.containsKey (שם)) {scopedObjects.put (שם, objectFactory.getObject ()); } להחזיר scopedObjects.get (שם); }

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

2.3. רישום התקשרות חוזרת להשמדה

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

@ Override register void registerDestructionCallback (שם מחרוזת, התקשרות חוזרת ניתן להריץ) {destinationCallbacks.put (שם, התקשרות חוזרת); }

2.4. הסרת אובייקט מההיקף

לאחר מכן, בואו ליישם את לְהַסִיר שיטה, המסירה את האובייקט שצוין מההיקף ומסירה גם את החזרת ההרס הרשומה שלו, ומחזירה את האובייקט שהוסר:

הסרת אובייקט ציבורי @Override (שם מחרוזת) {DestinationCallbacks.remove (שם); להחזיר scopedObjects.remove (שם); }

ציין זאת באחריות המתקשר לבצע את השיחה החוזרת ולהשמיד את האובייקט שהוסר.

2.5. קבלת מזהה השיחה

עכשיו, בוא נבצע את getConversationId שיטה. אם ההיקף שלך תומך במושג מזהה שיחה, היית מחזיר אותו לכאן. אחרת, האמנה היא לחזור ריק:

@ עקוף מחרוזת ציבורית getConversationId () {להחזיר "דייר"; }

2.6. פתרון אובייקטים הקשריים

לבסוף, בואו ליישם את resolveContextualObject שיטה. אם ההיקף שלך תומך במספר אובייקטים הקשריים, היית מקשר כל אחד לערך מפתח, ותחזיר את האובייקט המתאים לסיפוק מַפְתֵחַ פָּרָמֶטֶר. אחרת, האמנה היא לחזור ריק:

@Override ציבור אובייקטים resolveContextualObject (מפתח מחרוזת) {return null; }

3. רישום ההיקף המותאם אישית

כדי להפוך את מיכל האביב למודע להיקף החדש שלך, עליך לרשום אותו דרך registerScope שיטה על א ConfigurableBeanFactory למשל. בואו נסתכל על ההגדרה של שיטה זו:

void registerScope (String scopeName, Scope scope);

הפרמטר הראשון, scopeName, משמש לזיהוי / ציון היקף לפי שמו הייחודי. הפרמטר השני, תְחוּם, הוא מופע ממשי של המנהג תְחוּם יישום שברצונך לרשום ולהשתמש בו.

בואו ניצור מותאם אישית BeanFactoryPostProcessor ורשום את ההיקף המותאם אישית שלנו באמצעות ConfigurableListableBeanFactory:

מחלקה ציבורית TenantBeanFactoryPostProcessor מיישמת את BeanFactoryPostProcessor {@Override public void postProcessBeanFactory (מפעל ConfigurableListableBeanFactory) זורק BeansException {factory.registerScope ("דייר", TenantScope חדש ()); }}

עכשיו, בואו נכתוב שיעור תצורה של אביב אשר טוען את שלנו BeanFactoryPostProcessor יישום:

@Configuration public class TenantScopeConfig {@Bean public static BeanFactoryPostProcessor beanFactoryPostProcessor () {להחזיר TenantBeanFactoryPostProcessor חדש (); }}

4. שימוש בהיקף המותאם אישית

כעת, לאחר שרשמנו את היקף המותאם אישית שלנו, אנו יכולים להחיל אותו על כל אחד מהשעועית שלנו בדיוק כפי שהיינו עושים עם כל שעועית אחרת המשתמשת בהיקף שאינו קְלָף בּוֹדֵד (היקף ברירת המחדל) - באמצעות @תְחוּם ביאור וציון היקף המותאם אישית שלנו לפי שם.

בואו ניצור פשוט TenantBean class - אנו נכריז על שעועית בהיקף דייר מסוג זה עוד רגע:

מחלקה ציבורית TenantBean {שם פרטי מחרוזת סופי; TenantBean ציבורי (שם מחרוזת) {this.name = שם; } חלל ציבורי sayHello () {System.out.println (String.format ("שלום מ-% s מסוג% s", this.name, this.getClass (). getName ())); }}

שים לב שלא השתמשנו ברמת הכיתה @רְכִיב ו @תְחוּם ביאורים על כיתה זו.

עכשיו, בואו נגדיר כמה שעועית בהיקף דייר בכיתת תצורה:

@Configuration מחלקה ציבורית TenantBeansConfig {@Scope (scopeName = "tenant") @Bean public TenantBean foo () {להחזיר TenantBean חדש ("foo"); } @ Scope (scopeName = "דייר") @ סרגל TenantBean ציבורי () {להחזיר TenantBean חדש ("בר"); }}

5. בדיקת ההיקף המותאם אישית

בואו לכתוב מבחן כדי לממש את תצורת ההיקף המותאמת אישית שלנו על ידי טעינת an ApplicationContext, רישום שלנו תְצוּרָה שיעורים ואחזור שעועית הדיירים שלנו:

@Test ציבורי סופי בטל כאשר RegisterScopeAndBeans_thenContextContainsFooAndBar () {AnnotationConfigApplicationContext ctx = חדש AnnotationConfigApplicationContext (); נסה את {ctx.register (TenantScopeConfig.class); ctx.register (TenantBeansConfig.class); ctx.refresh (); TenantBean foo = (TenantBean) ctx.getBean ("foo", TenantBean.class); foo.sayHello (); סרגל TenantBean = (TenantBean) ctx.getBean ("בר", TenantBean.class); bar.sayHello (); מפה foos = ctx.getBeansOfType (TenantBean.class); assertThat (foo, not (equalTo (bar))); assertThat (foos.size (), equalTo (2)); assertTrue (foos.containsValue (foo)); assertTrue (foos.containsValue (bar)); BeanDefinition fooDefinition = ctx.getBeanDefinition ("foo"); BeanDefinition barDefinition = ctx.getBeanDefinition ("בר"); assertThat (fooDefinition.getScope (), equalTo ("דייר")); assertThat (barDefinition.getScope (), equalTo ("דייר")); } סוף סוף {ctx.close (); }}

והתפוקה מהבדיקה שלנו היא:

שלום מ foo מסוג org.baeldung.customscope.TenantBean שלום מהסוג org.baeldung.customscope.TenantBean

6. מסקנה

במדריך מהיר זה, הראינו כיצד להגדיר, לרשום ולהשתמש בהיקף מותאם אישית באביב.

תוכל לקרוא עוד על היקפים מותאמים אישית בעיון מסגרת האביב. אתה יכול גם להסתכל על יישומי אביב שונים תְחוּם שיעורים במאגר האביב Framework ב- GitHub.

כרגיל, תוכלו למצוא את דוגמאות הקוד המשמשות במאמר זה בפרויקט GitHub.


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