Memahami getBean () pada musim bunga

1. Pengenalan

Dalam tutorial ini, kita akan melalui pelbagai varian kaedah BeanFactory.getBean () .

Ringkasnya, seperti yang ditunjukkan oleh nama kaedah, ini bertanggungjawab untuk mengambil contoh kacang dari bekas Spring .

2. Persediaan Kacang Musim Bunga

Pertama, mari kita tentukan beberapa biji musim bunga untuk ujian. Terdapat beberapa cara di mana kita dapat memberikan definisi kacang untuk wadah Spring, tetapi dalam contoh kita, kita akan menggunakan konfigurasi Java berdasarkan anotasi:

@Configuration class AnnotationConfig { @Bean(name = {"tiger", "kitty"}) @Scope(value = "prototype") Tiger getTiger(String name) { return new Tiger(name); } @Bean(name = "lion") Lion getLion() { return new Lion("Hardcoded lion name"); } interface Animal {} } 

Kami telah mencipta dua biji. Lion mempunyai skop singleton lalai. Tiger secara eksplisit ditetapkan untuk skop prototaip. Selain itu, harap maklum bahawa kami menentukan nama untuk setiap kacang yang akan kami gunakan dalam permintaan selanjutnya.

3. API getBean ()

BeanFactory menyediakan lima tandatangan yang berbeza dari kaedah getBean () yang akan kita kaji dalam bahagian berikut.

3.1. Mengambil Kacang dengan Nama

Mari lihat bagaimana kita boleh mendapatkan contoh kacang Lion menggunakan namanya:

Object lion = context.getBean("lion"); assertEquals(Lion.class, lion.getClass());

Dalam varian ini, kami memberikan nama, dan sebagai balasannya, kami mendapat contoh kelas Objek jika kacang dengan nama yang diberikan ada dalam konteks aplikasi. Jika tidak, kedua-duanya dan semua pelaksanaan lain membuang NoSuchBeanDefinitionException sekiranya pencarian kacang gagal.

Kelemahan utamanya ialah setelah mengambil kacang itu, kita harus memasukkannya ke jenis yang dikehendaki. Ini mungkin menghasilkan pengecualian lain jika kacang yang dikembalikan mempunyai jenis yang berbeza dari yang kita harapkan .

Anggaplah kita berusaha mendapatkan Harimau menggunakan nama "singa". Apabila kami memberikan hasilnya ke Tiger , ia akan membuang ClassCastException :

assertThrows(ClassCastException.class, () -> { Tiger tiger = (Tiger) context.getBean("lion"); });

3.2. Mengambil Kacang mengikut Nama dan Jenis

Di sini kita perlu menentukan nama dan jenis kacang yang diminta:

Lion lion = context.getBean("lion", Lion.class);

Berbanding dengan kaedah sebelumnya, kaedah ini lebih selamat kerana kita mendapat maklumat mengenai ketidakcocokan jenis dengan serta-merta:

assertThrows(BeanNotOfRequiredTypeException.class, () -> context.getBean("lion", Tiger.class)); }

3.3. Mengambil Kacang mengikut Jenis

Dengan varian ketiga getBean (), cukup untuk menentukan jenis kacang sahaja:

Lion lion = context.getBean(Lion.class);

Dalam kes ini, kita perlu memberi perhatian khusus kepada hasil yang mungkin tidak jelas :

assertThrows(NoUniqueBeanDefinitionException.class, () -> context.getBean(Animal.class)); }

Dalam contoh di atas, kerana kedua-dua Singa dan Harimau menerapkan antara muka Haiwan , hanya menentukan jenis tidak cukup untuk menentukan hasilnya dengan jelas. Oleh itu, kami mendapat NoUniqueBeanDefinitionException .

3.4. Mengambil Kacang dengan Nama dengan Parameter Pembina

Sebagai tambahan kepada nama kacang, kami juga boleh melewati parameter pembina:

Tiger tiger = (Tiger) context.getBean("tiger", "Siberian");

Kaedah ini sedikit berbeza kerana hanya berlaku untuk kacang dengan skop prototaip .

Dalam kes single, kita akan mendapat BeanDefinitionStoreException.

Kerana kacang prototaip akan mengembalikan instance yang baru dibuat setiap kali diminta dari wadah aplikasi, kami dapat memberikan parameter konstruktor saat dalam perjalanan ketika memanggil getBean () :

Tiger tiger = (Tiger) context.getBean("tiger", "Siberian"); Tiger secondTiger = (Tiger) context.getBean("tiger", "Striped"); assertEquals("Siberian", tiger.getName()); assertEquals("Striped", secondTiger.getName());

Seperti yang kita lihat, setiap Harimau mendapat nama yang berbeza sesuai dengan apa yang kita tetapkan sebagai parameter kedua ketika meminta kacang.

3.5. Mengambil Kacang mengikut Jenis Dengan Parameter Pembina

Kaedah ini serupa dengan kaedah terakhir, tetapi kita perlu memberikan jenis dan bukannya nama sebagai argumen pertama:

Tiger tiger = context.getBean(Tiger.class, "Shere Khan"); assertEquals("Shere Khan", tiger.getName());

Sama seperti pengambilan kacang dengan nama dengan parameter konstruktor, kaedah ini hanya berlaku untuk kacang dengan skop prototaip .

4. Pertimbangan Penggunaan

Walaupun didefinisikan dalam antara muka BeanFactory , kaedah getBean () paling sering diakses melalui ApplicationContext. Biasanya, kami tidak mahu menggunakan kaedah getBean () secara langsung dalam program kami .

Kacang harus diuruskan oleh bekas. Sekiranya kita ingin menggunakan salah satu daripadanya, kita harus bergantung pada suntikan kebergantungan daripada panggilan terus ke ApplicationContext.getBean () . Dengan begitu, kita dapat mengelakkan percampuran logik aplikasi dengan perincian yang berkaitan dengan kerangka.

5. Kesimpulan

Dalam tutorial ringkas ini, kami menjalani semua pelaksanaan kaedah getBean () dari antara muka BeanFactory dan menerangkan kelebihan dan kekurangan masing-masing.

Semua contoh kod yang ditunjukkan di sini boleh didapati di GitHub.