ההבדל בין BeanFactory לבין ApplicationContext
1. סקירה כללית
מסגרת האביב מגיעה עם שני מכולות IOC - BeanFactory ו ApplicationContext. ה BeanFactory היא הגרסה הבסיסית ביותר של מכולות IOC, ו- ApplicationContext מרחיב את התכונות של BeanFactory.
במדריך מהיר זה נבין את ההבדלים המשמעותיים בין שני מיכלי ה- IOC הללו עם דוגמאות מעשיות.
2. טעינה עצלה לעומת העמסה נלהבת
BeanFactory טוען שעועית לפי דרישה, בעוד ApplicationContext טוען את כל השעועית בעת ההפעלה. לכן, BeanFactory הוא קל משקל לעומת ApplicationContext. בואו נבין את זה עם דוגמא.
2.1. טוען עצלן עם BeanFactory
נניח שיש לנו שיעור שעועית יחיד סטוּדֶנט בשיטה אחת:
תלמיד בכיתה ציבורית {בוליאני סטטי ציבורי isBeanInstantiated = false; public void postConstruct () {setBeanInstantiated (true); } // קובעי סטנדרטים וגטרים}
נגדיר את postConstruct () שיטה כמו שיטת init בשלנו BeanFactory קובץ תצורה, ioc-container-difference-example.xml:
עכשיו, בואו נכתוב מקרה מבחן שיוצר a BeanFactory כדי לבדוק אם הוא טוען את סטוּדֶנט אפונה:
@Test הציבור בטל כאשר BFInitialized_thenStudentNotInitialized () {Resource res = new ClassPathResource ("ioc-container-difference-example.xml"); מפעל BeanFactory = XmlBeanFactory חדש (res); assertFalse (Student.isBeanInstantiated ()); }
פה, ה סטוּדֶנט האובייקט אינו מאותחל. במילים אחרות, רק ה BeanFactory מאותחל. השעועית שהוגדרה אצלנו BeanFactory יוטען רק כאשר אנו קוראים במפורש ל- getBean () שיטה.
בואו נבדוק את האתחול של שלנו סטוּדֶנט שעועית במקום שאנחנו קוראים לו באופן ידני getBean () שיטה:
@ מבחן ציבורי בטל כאשר BFInitialized_thenStudentInitialized () {Resource res = new ClassPathResource ("ioc-container-difference-example.xml"); מפעל BeanFactory = XmlBeanFactory חדש (res); סטודנט סטודנט = (סטודנט) factory.getBean ("סטודנט"); assertTrue (Student.isBeanInstantiated ()); }
הנה ה סטוּדֶנט עומס שעועית בהצלחה. מכאן, ש BeanFactory טוען את השעועית רק כאשר היא נדרשת.
2.2. טוען להוט עם ApplicationContext
עכשיו, בואו נשתמש ApplicationContext במקום BeanFactory.
נגדיר רק ApplicationContext, והיא תטען את כל השעועית באופן מיידי באמצעות אסטרטגיית טעינה להוטה:
@ מבחן ציבורי בטל כאשר AppContInitialized_thenStudentInitialized () {ApplicationContext context = new ClassPathXmlApplicationContext ("ioc-container-difference-example.xml"); assertTrue (Student.isBeanInstantiated ()); }
הנה ה סטוּדֶנט האובייקט נוצר למרות שלא קראנו getBean () שיטה.
ApplicationContext נחשב למיכל IOC כבד מכיוון שאסטרטגיית הטעינה הלהוטה שלו טוענת את כל השעועית בעת ההפעלה. BeanFactory קל משוואה בהשוואה ויכול להיות שימושי במערכות מוגבלות זיכרון. על כל פנים, נראה בסעיפים הבאים מדוע ApplicationContext עדיף ברוב מקרי השימוש.
3. תכונות יישום ארגוני
ApplicationContext משפר BeanFactory בסגנון יותר ממוקד מסגרת ומספק מספר תכונות שמתאימות ליישומים ארגוניים.
למשל, זה מספק הודעות (i18n או בינלאומי) פונקציונליות, פרסום אירוע פונקציונליות, הזרקת תלות מבוססת ביאור, ו שילוב קל עם תכונות AOP של Spring. מלבד זאת, ה ApplicationContext תומך כמעט בכל סוגי טווחי השעועית, אך ה- BeanFactory תומך רק בשני טווחים - קְלָף בּוֹדֵד ו אב טיפוס. לכן, תמיד עדיף להשתמש בו ApplicationContext כאשר בונים יישומים ארגוניים מורכבים. ה ApplicationContext נרשם אוטומטית BeanFactoryPostProcessor ו מעבד BeanPost בעת ההפעלה. מצד שני, ה BeanFactory אינו רושם ממשקים אלה באופן אוטומטי. כדי להבין, בואו נכתוב שתי כיתות. ראשית, יש לנו את CustomBeanFactoryPostProcessor בכיתה, המיישמת את BeanFactoryPostProcessor: הנה, ביטלנו את postProcessBeanFactory () שיטה לבדוק את רישומה. שנית, יש לנו שיעור אחר, CustomBeanPostProcessor, אשר מיישמת מעבד BeanPost: הנה, ביטלנו את postProcessBeforeInitialization () שיטה לבדוק את רישומה. כמו כן, הגדרנו את שני הכיתות שלנו ioc-container-difference-example.xml קובץ תצורה: בואו נראה מקרה מבחן כדי לבדוק אם שתי המחלקות הללו נרשמות אוטומטית במהלך ההפעלה: כפי שאנו רואים מהבדיקה שלנו, רישום אוטומטי לא קרה. עכשיו, בואו נראה מקרה מבחן שמוסיף אותם ידנית ב- BeanFactory: הנה, השתמשנו ב- postProcessBeanFactory () שיטה לרישום CustomBeanFactoryPostProcessor וה addBeanPostProcessor () שיטה לרישום CustomBeanPostProcessor. שניהם נרשמים בהצלחה במקרה זה. כפי שציינו קודם, ApplicationContext רושם את שתי השיעורים באופן אוטומטי מבלי לכתוב קוד נוסף. בואו נאמת התנהגות זו במבחן יחידה: כמו שאנו יכולים לראות, ההרשמה האוטומטית של שני השיעורים מוצלחת במקרה הזה. לָכֵן, תמיד מומלץ להשתמש ApplicationContext כי אביב 2.0 (ומעלה) משתמש בכבדות מעבד BeanPost. ראוי גם לציין זאת אם אתה משתמש במישור BeanFactory, ואז תכונות כמו עסקאות ו- AOP לא ייכנסו לתוקף (לפחות לא בלי לכתוב שורות קוד נוספות). זה עלול להוביל לבלבול מכיוון ששום דבר לא ייראה לא בסדר בתצורה. במאמר זה ראינו את ההבדלים העיקריים בין ApplicationContext ו BeanFactory עם דוגמאות מעשיות. ה ApplicationContext מגיע עם תכונות מתקדמות, כולל כמה המיועדות ליישומים ארגוניים, בעוד ש- BeanFactory מגיע עם תכונות בסיסיות בלבד. לכן, בדרך כלל מומלץ להשתמש ב- ApplicationContext, ו עלינו להשתמש BeanFactory רק כאשר צריכת הזיכרון קריטית. כמו תמיד, הקוד של המאמר זמין באתר GitHub.4. רישום אוטומטי של BeanFactoryPostProcessor ו מעבד BeanPost
4.1. רישום ב BeanFactory
מחלקה ציבורית CustomBeanFactoryPostProcessor מיישמת BeanFactoryPostProcessor {בוליאני סטטי פרטי isBeanFactoryPostProcessorRegistered = false; @ Override public void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) {setBeanFactoryPostProcessorRegistered (true); } // קובעי סטנדרטים וגטרים}
מחלקה ציבורית CustomBeanPostProcessor מיישמת BeanPostProcessor {בוליאני סטטי פרטי isBeanPostProcessorRegistered = false; @Override אובייקט ציבורי postProcessBeforeInitialization (שעועית אובייקט, שם מחרוזת) {setBeanPostProcessorRegistered (true); שעועית להחזיר; } // קובעי סטנדרטים וגטרים}
@ מבחן ציבורי בטל כאשר BFInitialized_thenBFPProcessorAndBPProcessorNotRegAutomatically () {Resource res = new ClassPathResource ("ioc-container-difference-example.xml"); ConfigurableListableBeanFactory מפעל = XmlBeanFactory חדש (res); assertFalse (CustomBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered ()); assertFalse (CustomBeanPostProcessor.isBeanPostProcessorRegistered ()); }
@ מבחן ציבורי בטל כאשר BPFPProcessorAndBPProcessorRegisteredManually_thenReturnTrue () {Resource res = new ClassPathResource ("ioc-container-difference-example.xml"); ConfigurableListableBeanFactory מפעל = XmlBeanFactory חדש (res); CustomBeanFactoryPostProcessor beanFactoryPostProcessor = חדש CustomBeanFactoryPostProcessor (); beanFactoryPostProcessor.postProcessBeanFactory (מפעל); assertTrue (CustomBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered ()); CustomBeanPostProcessor beanPostProcessor = CustomBeanPostProcessor חדש (); factory.addBeanPostProcessor (beanPostProcessor); סטודנט סטודנט = (סטודנט) factory.getBean ("סטודנט"); assertTrue (CustomBeanPostProcessor.isBeanPostProcessorRegistered ()); }
4.2. רישום ב ApplicationContext
@Test ציבורי בטל כאשרAppContInitialized_thenBFPostProcessorAndBPostProcessorRegisteredAutomatically () {ApplicationContext context = new ClassPathXmlApplicationContext ("ioc-container-difference-example.xml"); assertTrue (CustomBeanFactoryPostProcessor.isBeanFactoryPostProcessorRegistered ()); assertTrue (CustomBeanPostProcessor.isBeanPostProcessorRegistered ()); }
5. מסקנה