JavaRush /בלוג Java /Random-HE /מסגרת אביב. מבוא
Marchello
רָמָה
Санкт-Петербург

מסגרת אביב. מבוא

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

אתחול ההקשר.

אז בואו נתחיל עם היסודות. לדעתי, אחת הנקודות החשובות ביותר היא להבין כיצד מוגדר ההקשר והשעועית מאותחלת. כפי שאתה יודע, לפני שהאביב מתחיל לעבוד, יש להגדיר אותו. בתקופות קדומות, זה נעשה באמצעות קבצי xml (בחלק מהפרויקטים, בעיקר ישנים, הם ממשיכים לעשות זאת עד היום). הנה דוגמה קטנה לקובץ תצורה כזה:
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" class="ru.javarush.HelloWorld">
       <property name="message" value="Hello World!"/>
   </bean>

</beans>
בגדול, זה מספיק כדי ליצור כמה בקרים ולהשיק סטארט-אפ (שלא ימריא). אבל איך התצורה הזו תגרום לאביב לעבוד? וכאן הדברים נעשים מעניינים. על מנת שהתצורה שלנו תובן על ידי אביב, יש XmlBeanDefinitionReader. BeanDefinitionזהו רכיב Spring פנימי שסורק (מנתח) xml ויוצר על סמך מה שכתבנו שם . BeanDefinitionהוא חפץ המאחסן מידע על השעועית. זה כולל: מאיזה מחלקה צריך ליצור אותו (השעועית); תְחוּם; האם מותקן אתחול עצל; האם יש צורך לאתחל לפני שעועית זו עוד ועוד מאפיינים המתוארים ב-xml. כל המתקבלים BeanDefinitionמתווספים ל- HashMap, שבהם המזהה הוא שם השעועית (שנקבע על ידך או הוקצה על ידי Spring) והאובייקט BeanDefinitionעצמו. לאחר שהכל BeanDefinitionנוצר, גיבור חדש מופיע על הבמה - BeanFactory. אובייקט זה חוזר על HashMap’es BeanDefinition, יוצר שעועית המבוססת עליהם ומכניס אותם למיכל IoC. יש כאן ניואנס, למעשה, כאשר האפליקציה מתחילה, מיכל IoC יכיל שעועית בעלי היקף Singleton (מוגדר כברירת מחדל), בעוד השאר נוצרים בעת הצורך (אב-טיפוס, בקשה, סשן). ועכשיו סטייה קטנה, בואו נכיר דמות אחרת.

הכירו את BeanPostProcessor. (BPP)

מעבד פוסט שעועיתהעובדה היא שעועית היא לא בהכרח סוג של היגיון עסקי עבור היישום שלך. שעועית נקראת גם שעועית תשתית. בקיצור, שעועית תשתית היא מחלקה שמגדירה את שעועית ההיגיון העסקי שלך (כן, יותר מדי שעועית). אני אספר לך יותר על זה למטה, אבל כדי להבהיר קצת יותר מה בדיוק BPP מגדיר, אתן דוגמה. האם כולם מכירים את התקציר @Autowired? לכן, אתה AutowiredAnnotationBeanPostProcessorאחראי לוודא שכל השיעורים שלך מוטמעים זה בזה. אוקנימית

בוא נחזור ל-BeanFactory

כאשר יודעים כעת על BPP, יש צורך להבהיר כי בעת איטרציה של over HashMap's, BeanDefinitionכולם נוצרים תחילה וממוקמים בנפרד (לא במיכל IoC) BeanPostProcessor. לאחר מכן, נוצרים שעועית רגילה של ההיגיון העסקי שלנו, מוכנסות למיכל IoC, והתצורה שלהם מתחילה באמצעות BPPs דחויים בנפרד. וככה זה קורה, לכל BPP יש 2 שיטות:
postProcessorBeforeInitialization(Object bean, String beanName);
postProcessorAfterInitialization(Object bean, String beanName);
עובר דרך הפחים שלנו פעמיים. בפעם הראשונה נקראת השיטה postProcessorBeforeInitialization, ובפעם השנייה נקראת השיטה postProcessorAfterInitialization. בוודאי עלתה השאלה מדוע יש צורך בשתי שיטות, הרשו לי להסביר. העובדה היא שכדי לעבד הערות מסוימות (כגון @Transactional, למשל), השעועית שלנו מוחלפת במחלקת פרוקסי. כדי להבין למה זה נעשה, אתה צריך לדעת איך זה עובד @Transactional, וכך זה עובד. עליך להוסיף עוד כמה שורות קוד לשיטה המסומנת בהערה זו תוך כדי תנועה. איך לעשות את זה? זה נכון, על ידי יצירת מחלקת proxy, שבתוכה יתווסף הקוד הדרוש לשיטה הנדרשת. עכשיו דמיינו את המצב הזה, יש לנו שיעור:
class A {
    @Autowired
    private SomeClass someClass;

    @Transactional
    public void method() {
        // модификатор доступа обязательно public
    }
}
לכיתה זו יש 2 הערות @Autowiredו- @Transactional. שתי ההערות מעובדות על ידי BPPs שונים. אם זה יעבוד קודם AutowiredBPP, אז הכל יהיה בסדר, אבל אם לא, אז ניתקל בבעיה הזו. העובדה היא שכאשר נוצרת מחלקת ה-proxy, כל המטא מידע הולך לאיבוד. במילים אחרות, לא יהיה מידע על ההערה @Autowiredבמחלקת ה-proxy, ולכן AutowiredBPPהוא לא יעבוד, מה שאומר שהשדה שלנו someClassיקבל את הערך null, שככל הנראה יוביל ל-NPE. כדאי גם לדעת שבין קריאות למתודה נקראת postProcessorBeforeInitializationהשיטה , אם יש כזו. זה בעצם הבנאי השני, אבל ההבדל הוא שברגע זה כל התלות שלנו כבר מוטמעות במחלקה ואנחנו יכולים לגשת אליהן מה- method. אז, שוב אלגוריתם אתחול ההקשר: postProcessorAfterInitializationinitinit
  1. XmlBeanDefinitionReaderסורק את קובץ ה-xml שלנו.
  2. יוצר BeanDefinitionומכניס אותם HashMap.
  3. בא BeanFactoryומזה HashMapבנפרד מצטבר כל BeanPostProcessorה'ים.
  4. יוצר BeanDefinitionשעועית מ-'s ומניח אותם במיכל IoC.
  5. כאן מגיעים BPPs ומגדירים את הפולים האלה בשתי שיטות.
  6. מוּכָן.
בעצם, זה הכל, כתבו אם אהבתם את המאמר והאם כדאי להמשיך לכתוב מדריכים כאלה.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION