אביב NoSuchBeanDefinitionException

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

במאמר זה אנו דנים ב- אביב org.springframework.beans.factory.NoSuchBeanDefinitionException זה חריג נפוץ שנזרק על ידי BeanFactory כשמנסים לפתור שעועית שפשוט לא מוגדרת בהקשר האביבי.

נדגים את הסיבות האפשריות לבעיה זו ואת הפתרונות הזמינים.

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

2. סיבה: שום שעועית מזכה מסוג [...] לא נמצאה כתלות

הסיבה השכיחה ביותר לחריג זה היא פשוט ניסיון להזריק שעועית שאינה מוגדרת. לדוגמה - BeanB חיווט משתף פעולה - BeanA:

@Component בכיתה ציבורית BeanA {@ תלות פרטית מאושרת ב- BeanB; // ...}

עכשיו, אם התלות - BeanB - אינו מוגדר בהקשר האביב, תהליך האתחול ייכשל עם לא יוצא מן הכלל הגדרת שעועית כזו:

org.springframework.beans.factory.NoSuchBeanDefinitionException: שום שעועית מזכה מסוג [com.baeldung.packageB.BeanB] לא נמצאה לתלות: צפויה לפחות שעועית אחת שמתאימה למועמדת חוט אוטומטי לתלות זו. הערות תלות: {@ org.springframework.beans.factory.annotation.Autowired (חובה = נכון)}

הסיבה מסומנת בבירור באביב: "צפוי לפחות שעועית אחת שתקבל מועמד לחוט אוטומטי לתלות זו

סיבה אחת BeanB לא יכול להתקיים בהקשר - אם קטניות נאספות אוטומטית על ידי סריקת מסלול כיתה, ואם BeanB מסומנת כהלכה כשעועית (@רְכִיב, מאגר @, @שֵׁרוּת, @בקרוכו ') - האם זה יכול להיות מוגדר ב חבילה שלא נסרקת על ידי אביב:

חבילה com.baeldung.packageB; @Component בכיתה ציבורית BeanB {...}

אמנם ניתן להגדיר את סריקת שביל הכיתה באופן הבא:

@Configuration @ComponentScan ("com.baeldung.packageA") בכיתה ציבורית ContextWithJavaConfig {...}

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

3. סיבה: שדה [...] ב [...] נדרש שעועית מסוג [...] שלא ניתן היה למצוא

ביישום Spring Boot עבור התרחיש הנ"ל, אנו מקבלים מסר אחר.

בואו ניקח את אותה הדוגמה איפה BeanB מחובר BeanA אבל זה לא מוגדר:

@Component בכיתה ציבורית BeanA {@ תלות פרטית מאושרת ב- BeanB; // ...}

אם ננסה להריץ את היישום הפשוט הזה, זה מנסה לטעון BeanA:

@SpringBootApplication מחלקה ציבורית NoSuchBeanDefinitionDemoApp {main public static void (String [] args) {SpringApplication.run (NoSuchBeanDefinitionDemoApp.class, args); }}

היישום נכשל בהתחלת הודעת השגיאה:

*************************** הבקשה לא הצליחה להתחיל ****************** ******** תיאור: תלות שדה ב- com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanA דרשה שעועית מסוג 'com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB' שלא ניתן היה למצוא. פעולה: שקול להגדיר שעועית מסוג 'com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB' בתצורה שלך.

פה, com.baeldung.springbootmvc.nosuchbeandefinitionexception היא החבילה עבור BeanA, BeanB ו NoSuchBeanDefinitionDemoApp.

קטע הדוגמא למשל נמצא בפרויקט Github זה.

4. סיבה: לא מוגדרת שעועית מזכה מסוג [...]

גורם נוסף לחריג הוא קיומן של שתי הגדרות שעועית בהקשר, במקום אחת. לדוגמא, אם ממשק - IBeanB מיושם על ידי שתי שעועית - BeanB1 ו BeanB2:

@Component בכיתה ציבורית BeanB1 מיישמת את IBeanB {//} @Component class class BeanB2 מיישמת את IBeanB {//}

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

@Component ברמה הציבורית BeanA {@ תלות פרטית מאושרת ב- IBeanB; ...}

ושוב, זה יביא ל- NoSuchBeanDefinitionException נזרק על ידי BeanFactory:

נגרם על ידי: org.springframework.beans.factory.NoUniqueBeanDefinitionException: לא מוגדרת שעועית מזכה מסוג [com.baeldung.packageB.IBeanB]: צפויה שעועית תואמת יחידה אך נמצאה 2: beanB1, beanB2

באופן דומה, האביב מציין בבירור את הסיבה לכשל בחיווט: "צפוי שעועית תואמת יחיד אך מצאתי 2".

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

לפני שינוי זה, החריג לעיל היה:

נגרם על ידי: org.springframework.beans.factory.NoSuchBeanDefinitionException: לא מוגדרת שעועית מזכה מסוג [com.baeldung.packageB.IBeanB]: צפויה שעועית תואמת יחידה אך נמצאה 2: beanB1, beanB2

אחד הפתרון לבעיה זו הוא שימוש ב- @מַגְדִיר ביאור כדי לציין בדיוק את שם השעועית שאנו רוצים לחבר:

@Component בכיתה ציבורית BeanA {@Autowired @Qualifier ("beanB2") תלות פרטית ב- IBeanB; ...}

עכשיו לאביב יש מספיק מידע כדי להחליט איזה שעועית להזריק - BeanB1 אוֹ BeanB2 (שם ברירת המחדל של BeanB2 הוא beanB2).

5. סיבה: לא מוגדרת שום שעועית ששמה [...]

א NoSuchBeanDefinitionException עשוי גם להיות מושלך כאשר שעועית שאינה מוגדרת היא התבקש לפי שם מהקשר האביב:

@Component בכיתה ציבורית מיישמת BeanA InitializingBean {@Autowired פרטי ApplicationContext הקשר; @ ביטול ציבורי בטל afterPropertiesSet () {context.getBean ("someBeanName"); }}

במקרה זה, אין הגדרת שעועית עבור "someBeanName" - מה שמוביל לחריג הבא:

נגרם על ידי: org.springframework.beans.factory.NoSuchBeanDefinitionException: לא מוגדרת שעועית בשם 'someBeanName'

שוב, האביב מציין בצורה ברורה ותמציתית את הסיבה לכישלון: "לא מוגדרת שעועית בשם X“.

6. סיבה: שעועית מסוכרת

כאשר שעועית בהקשר מתבצעת באמצעות מנגנון ה- Dynamic Proxy של JDK, אז ה- proxy לא יאריך את שעועית היעד (עם זאת, הוא יישם את אותם ממשקים).

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

סיבה שכיחה מאוד שהשעועית עשויה להיות בסביבה היא תמיכת עסקאות אביבית - כלומר שעועית עם הערות @ Transactional.

לדוגמא, אם שירות A. מזריק שירות B.ושני השירותים הם עסקיים, הזרקה לפי הגדרת הכיתה לא יעבוד:

@Service @ ServiceA בכיתה ציבורית Transactional מיישמת את IServiceA {@ ServiceB שירות פרטי פרטי; ...} @Service @Transactional public class ServiceB מיישם את IServiceB {...}

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

@Service @ שירות ציבורי Transactional מיישם את IServiceA {@ שירות ISBB פרטי פרטי; ...} @Service @Transactional Class Class Service מיישם את IServiceB {...}

7. מסקנה

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

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

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