Memahami getBean () di Spring

1. Perkenalan

Dalam tutorial ini, kita akan membahas varian berbeda dari metode BeanFactory.getBean () .

Sederhananya, seperti yang disarankan oleh nama metode, ini bertanggung jawab untuk mengambil instance kacang dari wadah Spring .

2. Setup Kacang Musim Semi

Pertama, mari kita tentukan beberapa kacang musim semi untuk pengujian. Ada beberapa cara di mana kita dapat memberikan definisi kacang untuk wadah Spring, tetapi dalam contoh kita, kita akan menggunakan konfigurasi Java berbasis 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 membuat dua kacang. Lion memiliki cakupan tunggal default. Tiger secara eksplisit diatur ke ruang lingkup prototipe. Selain itu, harap dicatat bahwa kami menetapkan nama untuk setiap kacang yang akan kami gunakan dalam permintaan selanjutnya.

3. API getBean ()

BeanFactory menyediakan lima tanda tangan berbeda dari metode getBean () yang akan kita periksa di subbagian berikut.

3.1. Mengambil Bean dengan Nama

Mari kita lihat bagaimana kita bisa mengambil instance Lion bean menggunakan namanya:

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

Dalam varian ini, kami memberikan nama, dan sebagai gantinya, kami mendapatkan instance kelas Object jika kacang dengan nama yang diberikan ada dalam konteks aplikasi. Jika tidak, implementasi ini dan semua lainnya akan menampilkan NoSuchBeanDefinitionException jika pencarian kacang gagal.

Kerugian utamanya adalah setelah mengambil kacang, kita harus membuangnya ke jenis yang diinginkan. Ini dapat menghasilkan pengecualian lain jika kacang yang dikembalikan memiliki jenis yang berbeda dari yang kami harapkan .

Misalkan kita mencoba mendapatkan harimau dengan menggunakan nama “singa”. Saat kami memberikan hasilnya ke Tiger , ClassCastException akan muncul :

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

3.2. Mengambil Bean berdasarkan Nama dan Jenis

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

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

Dibandingkan dengan metode sebelumnya, metode ini lebih aman karena kami mendapatkan informasi tentang ketidakcocokan tipe secara instan:

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

3.3. Mengambil Bean berdasarkan Jenis

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

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

Dalam kasus ini, kita perlu memberi perhatian khusus pada hasil yang berpotensi ambigu :

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

Dalam contoh di atas, karena Lion dan Tiger mengimplementasikan antarmuka Hewan , hanya menentukan jenis saja tidak cukup untuk menentukan hasilnya secara jelas. Oleh karena itu, kami mendapatkan NoUniqueBeanDefinitionException .

3.4. Mengambil Bean berdasarkan Nama dengan Parameter Konstruktor

Selain nama kacang, kita juga dapat mengirimkan parameter konstruktor:

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

Metode ini sedikit berbeda karena hanya berlaku untuk kacang dengan ruang lingkup prototipe .

Dalam kasus lajang, kita akan mendapatkan BeanDefinitionStoreException.

Karena prototipe bean akan mengembalikan instance yang baru dibuat setiap kali diminta dari wadah aplikasi, kita bisa menyediakan parameter konstruktor saat menjalankan 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 bisa kita lihat, setiap Tiger mendapatkan nama yang berbeda sesuai dengan apa yang kita tentukan sebagai parameter kedua saat meminta kacang.

3.5. Mengambil Bean berdasarkan Jenis Dengan Parameter Pembuat

Metode ini analog dengan yang terakhir, tetapi kita perlu meneruskan tipe alih-alih nama sebagai argumen pertama:

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

Mirip dengan mengambil kacang berdasarkan nama dengan parameter konstruktor, metode ini hanya berlaku untuk kacang dengan cakupan prototipe .

4. Pertimbangan Penggunaan

Meskipun didefinisikan dalam antarmuka BeanFactory , metode getBean () paling sering diakses melalui ApplicationContext. Biasanya, kami tidak ingin menggunakan metode getBean () secara langsung di program kami .

Kacang harus dikelola oleh wadah. Jika kita ingin menggunakan salah satunya, kita harus mengandalkan injeksi dependensi daripada panggilan langsung ke ApplicationContext.getBean () . Dengan begitu, kita dapat menghindari pencampuran logika aplikasi dengan detail terkait kerangka kerja.

5. Kesimpulan

Dalam tutorial singkat ini, kami membahas semua implementasi metode getBean () dari antarmuka BeanFactory dan menjelaskan pro dan kontra masing-masing.

Semua contoh kode yang ditampilkan di sini tersedia di GitHub.