Spring BeanCreationException

1. Gambaran keseluruhan

Dalam artikel ini, kita membincangkan org.springframework.beans.factory.BeanCreationException Spring - ini adalah pengecualian yang sangat biasa yang dilemparkan ketika BeanFactory membuat biji definisi kacang dan menghadapi masalah. Artikel ini akan membincangkan penyebab paling umum pengecualian ini bersama dengan penyelesaiannya.

2. Sebab: org.springframework.beans.factory.NoSuchBeanDefinitionException

Sejauh ini penyebab BeanCreationException yang paling biasa adalah Spring cuba menyuntik kacang yang tidak ada dalam konteks.

Sebagai contoh, BeanA cuba menyuntik BeanB :

@Component public class BeanA { @Autowired private BeanB dependency; ... }

Sekiranya BeanB tidak dijumpai dalam konteks, maka pengecualian berikut akan dilemparkan (Kesalahan Membuat Bean):

Error creating bean with name 'beanA': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.baeldung.web.BeanB cpm.baeldung.web.BeanA.dependency; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.baeldung.web.BeanB] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Untuk mendiagnosis jenis masalah ini - pertama, pastikan kacang dinyatakan:

  • sama ada dalam fail konfigurasi XML menggunakan unsur
  • atau di kelas Java @Configuration melalui anotasi @Bean
  • atau dijelaskan dengan: @Component , @Repository , @Service , @Controller dan pengimbasan classpath aktif untuk pakej tersebut

Periksa juga bahawa fail atau kelas konfigurasi sebenarnya diambil oleh Spring dan dimuat ke dalam konteks utama.

3. Sebab: org.springframework.beans.factory.NoUniqueBeanDefinitionException

Sebab lain yang serupa untuk pengecualian penciptaan kacang adalah Spring yang berusaha menyuntik kacang mengikut jenis - iaitu antara muka - dan mencari dua atau lebih biji kacang yang melaksanakan antara muka tersebut dalam konteks.

Sebagai contoh, BeanB1 dan BeanB2 sama-sama melaksanakan antara muka yang sama:

@Component public class BeanB1 implements IBeanB { ... } @Component public class BeanB2 implements IBeanB { ... } @Component public class BeanA { @Autowired private IBeanB dependency; ... }

Ini akan menyebabkan pengecualian berikut dilemparkan oleh kilang kacang Spring:

Error creating bean with name 'beanA': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.baeldung.web.IBeanB com.baeldung.web.BeanA.b; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.baeldung.web.IBeanB] is defined: expected single matching bean but found 2: beanB1,beanB2

4. Sebab: org.springframework.beans.BeanInstantiationException

4.1. Pengecualian Tersuai

Selanjutnya adalah kacang yang membuang pengecualian semasa proses penciptaannya ; sampel yang dipermudahkan untuk memberi contoh dan memahami masalah dengan mudah adalah membuang pengecualian dalam pembentuk kacang:

@Component public class BeanA { public BeanA() { super(); throw new NullPointerException(); } ... }

Seperti yang dijangkakan, ini akan menyebabkan Spring gagal dengan cepat dengan pengecualian berikut:

Error creating bean with name 'beanA' defined in file [...BeanA.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.baeldung.web.BeanA]: Constructor threw exception; nested exception is java.lang.NullPointerException

4.2. java.lang.InstantiationException

Kemungkinan lain kejadian BeanInstantiationException ialah mendefinisikan kelas abstrak sebagai kacang dalam XML; ini harus dalam XML, kerana tidak ada cara untuk melakukannya dalam file Java @Configuration dan pengimbasan classpath akan mengabaikan kelas abstrak:

@Component public abstract class BeanA implements IBeanA { ... }

Dan definisi XML kacang:

Penyediaan ini akan menghasilkan pengecualian yang serupa:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'beanA' defined in class path resource [beansInXml.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.baeldung.web.BeanA]: Is it an abstract class?; nested exception is java.lang.InstantiationException

4.3. java.lang.NoSuchMethodException

Sekiranya kacang tidak mempunyai konstruktor lalai dan Spring mencuba untuk membuatnya dengan mencari konstruktor itu, ini akan menghasilkan pengecualian runtime; sebagai contoh:

@Component public class BeanA implements IBeanA { public BeanA(final String name) { super(); System.out.println(name); } }

Apabila kacang ini diambil oleh mekanisme pengimbasan classpath, kegagalannya adalah:

Error creating bean with name 'beanA' defined in file [...BeanA.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.baeldung.web.BeanA]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.baeldung.web.BeanA.()

Pengecualian serupa, tetapi lebih sukar untuk didiagnosis, mungkin berlaku apabila pergantungan Spring pada classpath tidak mempunyai versi yang sama ; ketidaksesuaian versi seperti ini boleh mengakibatkan NoSuchMethodException kerana perubahan API. Penyelesaian untuk masalah tersebut adalah memastikan semua perpustakaan Spring mempunyai versi yang sama dalam projek ini.

5. Sebab: org.springframework.beans.NotWritablePropertyException

Namun kemungkinan lain adalah menentukan kacang - BeanA - dengan merujuk kepada kacang lain - BeanB - tanpa mempunyai kaedah setter yang sesuai dalam BeanA :

@Component public class BeanA { private IBeanB dependency; ... } @Component public class BeanB implements IBeanB { ... }

Dan Konfigurasi Spring XML:

Sekali lagi, ini hanya dapat terjadi dalam Konfigurasi XML , kerana ketika menggunakan Java @Configuration , penyusun akan menjadikan masalah ini mustahil untuk dibuat semula.

Sudah tentu, untuk menyelesaikan masalah ini, setter perlu ditambahkan untuk IBeanB :

@Component public class BeanA { private IBeanB dependency; public void setDependency(final IBeanB dependency) { this.dependency = dependency; } }

6. Sebab: org.springframework.beans.factory.CannotLoadBeanClassException

Pengecualian ini dilemparkan apabila Spring tidak dapat memuat kelas kacang yang ditentukan - ini mungkin berlaku jika Spring XML Configuration mengandungi kacang yang tidak mempunyai kelas yang sesuai. Sebagai contoh, jika kelas BeanZ tidak wujud, definisi berikut akan menghasilkan pengecualian:

Punca utama jika ClassNotFoundException dan pengecualian sepenuhnya dalam kes ini adalah:

nested exception is org.springframework.beans.factory.BeanCreationException: ... nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [com.baeldung.web.BeanZ] for bean with name 'beanZ' defined in class path resource [beansInXml.xml]; nested exception is java.lang.ClassNotFoundException: com.baeldung.web.BeanZ

7. Kanak-kanak BeanCreationException

7.1. The org.springframework.beans.factory.BeanCurrentlyInCreationException

Salah satu subkelas BeanCreationException ialah BeanCurrentlyInCreationException ; ini biasanya berlaku semasa menggunakan suntikan konstruktor - contohnya, dalam kes kebergantungan pekeliling:

@Component public class BeanA implements IBeanA { private IBeanB beanB; @Autowired public BeanA(final IBeanB beanB) { super(); this.beanB = beanB; } } @Component public class BeanB implements IBeanB { final IBeanA beanA; @Autowired public BeanB(final IBeanA beanA) { super(); this.beanA = beanA; } }

Spring tidak akan dapat menyelesaikan senario pendawaian seperti ini dan hasil akhirnya adalah:

org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?

Pengecualian penuh sangat verbose:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'beanA' defined in file [...BeanA.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.baeldung.web.IBeanB]: : Error creating bean with name 'beanB' defined in file [...BeanB.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.baeldung.web.IBeanA]: : Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'beanB' defined in file [...BeanB.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.baeldung.web.IBeanA]: : Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanA': Requested bean is currently in creation: Is there an unresolvable circular reference?

7.2. The org.springframework.beans.factory.BeanIsAbstractException

Pengecualian instantiasi ini mungkin berlaku ketika Bean Factory berusaha untuk mengambil dan membuat kacang yang dinyatakan sebagai abstrak; sebagai contoh:

public abstract class BeanA implements IBeanA { ... }

Diisytiharkan dalam Konfigurasi XML sebagai:

Sekarang, jika kita cuba mengambil BeanA dari Spring Context dengan nama - contohnya semasa membuat kacang lain:

@Configuration public class Config { @Autowired BeanFactory beanFactory; @Bean public BeanB beanB() { beanFactory.getBean("beanA"); return new BeanB(); } }

Ini akan menyebabkan pengecualian berikut:

org.springframework.beans.factory.BeanIsAbstractException: Error creating bean with name 'beanA': Bean definition is abstract

Dan stacktrace pengecualian penuh:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'beanB' defined in class path resource [org/baeldung/spring/config/WebConfig.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public com.baeldung.web.BeanB com.baeldung.spring.config.WebConfig.beanB()] threw exception; nested exception is org.springframework.beans.factory.BeanIsAbstractException: Error creating bean with name 'beanA': Bean definition is abstract

8. Kesimpulannya

Pada akhir artikel ini, kita harus mempunyai peta yang jelas untuk menavigasi pelbagai sebab dan masalah yang mungkin menyebabkan BeanCreationException pada Musim Semi, serta pemahaman yang baik tentang bagaimana memperbaiki semua masalah ini.

Pelaksanaan semua contoh pengecualian boleh didapati di projek github - ini adalah projek berasaskan Eclipse, jadi mudah untuk diimport dan dijalankan sebagaimana adanya.