ה- BeanDefinitionOverrideException באביב אתחול

1. הקדמה

שדרוג Spring Boot 2.1 הפתיע כמה אנשים עם הופעות לא צפויות של BeanDefinitionOverrideException. זה יכול לבלבל כמה מפתחים ולגרום להם לתהות לגבי מה שקרה להתנהגות השעועית באביב.

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

2. תלות Maven

עבור פרויקט Maven לדוגמא שלנו, עלינו להוסיף את תלות Starter Spring Boot:

 org.springframework.boot spring-boot-starter 2.3.3.RELEASE 

3. עקיפת שעועית

שעועית קפיצית מזוהה בשמותיהן בתוך ApplicationContext.

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

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

4. שינוי תצורה עבור Spring Boot 2.1

Spring Boot 2.1 השבתת שעועית מושבתת כברירת מחדל כגישה הגנתית. המטרה העיקרית היא שימו לב מראש לשמות השעועית הכפולים כדי למנוע עקיפת שעועית בטעות.

לכן, אם אפליקציית Spring Boot שלנו מסתמכת על עקיפת שעועית, סביר מאוד להניח שהיא תיתקל ב- BeanDefinitionOverrideException לאחר שדרוג גרסת Spring Boot ל -2.1 ואילך.

בחלקים הבאים נבחן דוגמה שבה BeanDefinitionOverrideException ואז יתרחש כמה פתרונות.

5. זיהוי השעועית בסכסוך

בואו ניצור שתי תצורות קפיץ שונות, כל אחת עם testBean () שיטה, לייצר את BeanDefinitionOverrideException:

@Configuration מחלקה ציבורית TestConfiguration1 {class TestBean1 {שם מחרוזת פרטי; // סטרים וקובעים סטנדרטיים} @Bean הציבור TestBean1 testBean () {להחזיר TestBean1 חדש (); }} 
@Configuration מחלקה ציבורית TestConfiguration2 {class TestBean2 {שם מחרוזת פרטי; // getters and setters סטנדרטיים} @Bean הציבור TestBean2 testBean () {להחזיר TestBean2 חדש (); }} 

לאחר מכן, ניצור את שיעור הבדיקה של Boot Boot:

@RunWith (SpringRunner.class) @SpringBootTest (classes = {TestConfiguration1.class, TestConfiguration2.class}) class public SpringBootBeanDefinitionOverrideExceptionIntegrationTest {@Test public void whenBeanOverridingAllowed_thenTestBean2OverreanTest_Test_Bean2OverridesTest {@TestBean2OverreanTest_TestBean2Overean = assertThat (testBean.getClass ()). isEqualTo (TestConfiguration2.TestBean2.class); }} 

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

הגדרת שעועית לא חוקית עם השם 'testBean' מוגדרת ב ... ... com.baeldung.beandefinitionoverrideexception.TestConfiguration2 ... לא ניתן לרשום הגדרת שעועית [... מוגדרת ב ... ... com.baeldung.beandefinitionoverrideexception.TestConfiguration2] עבור שעועית 'testBean' ... יש כבר [... מוגדר ב ... ... com.baeldung.beandefinitionoverrideexception.TestConfiguration1] מאוגד. 

שימו לב כי החריג מגלה שתי פיסות מידע חשובות.

הראשון הוא שם השעועית הסותרת, testBean:

הגדרת שעועית לא חוקית עם השם 'testBean' ... 

והשני מראה לנו את הנתיב המלא של התצורות המושפעות:

... com.baeldung.beandefinitionoverrideexception.TestConfiguration2 ... ... com.baeldung.beandefinitionoverrideexception.TestConfiguration1 ... 

כתוצאה מכך אנו יכולים לראות ששתי שעועית שונות מזוהות כ- testBean גורם לסכסוך. בנוסף, השעועית כלולה בתוך שיעורי התצורה תצורת מבחן 1 ו תצורת מבחן 2.

6. פתרונות אפשריים

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

לכן, הפיתרון האפשרי הראשון הוא לשנות את שם השעועית שלנו.

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

6.1. שינוי שמות שיטות

כברירת מחדל, אביב לוקח את השם של השיטות המבוארות כשמות שעועית.

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

@Bean הציבור TestBean1 testBean1 () {להחזיר TestBean1 חדש (); } 
@Bean הציבור TestBean2 testBean2 () {להחזיר TestBean2 חדש (); } 

6.2. @אפונה ביאור

האביב @אפונה ביאור הוא דרך נפוצה מאוד להגדרת שעועית.

לפיכך, אפשרות נוספת היא להגדיר את שֵׁם רכוש של @אפונה ביאור:

@Bean ("testBean1") TestBean1 testBean () ציבורי {להחזיר TestBean1 חדש (); } 
@Bean ("testBean2") TestBean1 publicBean1 () {להחזיר TestBean2 חדש (); } 

6.3. הערות סטריאוטיפ

דרך נוספת להגדיר שעועית היא ביאורים סטריאוטיפיים. עם האביב @ComponentScan אם התכונה מופעלת, אנו יכולים להגדיר את שמות השעועית שלנו ברמת הכיתה באמצעות ה- @רְכִיב ביאור:

מחלקה @Component ("testBean1") TestBean1 {שם מחרוזת פרטי; // סטרים וקובעים סטנדרטיים} 
מחלקה @Component ("testBean2") TestBean2 {שם מחרוזת פרטי; // סטרים וקובעים סטנדרטיים} 

6.4. שעועית שמגיעה מספריות של צד שלישי

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

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

עם זאת, אם איננו יכולים לשנות את אחת מההגדרות שעועית, הגדרת Spring Boot כך שתאפשר עקיפת שעועית יכולה להיות דרך לעקיפת הבעיה.

כדי לאפשר עקיפת שעועית, בואו נגדיר את spring.main.allow-bean-definition-overriding נכס ל נָכוֹן בשלנו application.properties קוֹבֶץ:

spring.main.allow-bean-definition-overriding = true 

בכך אנו אומרים ל- Spring Boot לאפשר לעקוף שעועית ללא כל שינוי בהגדרות שעועית.

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

7. מסקנה

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

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


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