Latar Belakang:
Saya memiliki aplikasi Spring 2.5 / Java / Tomcat. Ada kacang berikut, yang digunakan di seluruh aplikasi di banyak tempat
public class HibernateDeviceDao implements DeviceDao
dan kacang berikut yang baru:
public class JdbcDeviceDao implements DeviceDao
Kacang pertama dikonfigurasi jadi (semua kacang dalam paket disertakan)
<context:component-scan base-package="com.initech.service.dao.hibernate" />
Kacang kedua (baru) dikonfigurasi secara terpisah
<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
<property name="dataSource" ref="jdbcDataSource">
</bean>
Ini menghasilkan (tentu saja) dalam pengecualian saat memulai server:
pengecualian bersarang adalah org.springframework.beans.factory.NoSuchBeanDefinitionException: Tidak ada jenis kacang unik [com.sevenp.mobile.samplemgmt.service.dao.DeviceDao] yang ditentukan: diharapkan kacang pencocokan tunggal tetapi ditemukan 2: [deviceDao, jdbcDeviceDao]
dari kelas yang mencoba melakukan autowire kacang seperti ini
@Autowired
private DeviceDao hibernateDevicDao;
karena ada dua kacang yang menerapkan antarmuka yang sama.
Pertanyaan:
Apakah mungkin untuk mengkonfigurasi kacang sehingga
1. Saya tidak perlu mengubah kelas yang ada, yang sudah memiliki HibernateDeviceDao
autowired
2. masih bisa menggunakan kacang kedua (baru) seperti ini:
@Autowired
@Qualifier("jdbcDeviceDao")
Yaitu saya akan memerlukan cara untuk mengkonfigurasi HibernateDeviceDao
kacang sebagai kacang default untuk menjadi autowired, secara bersamaan memungkinkan penggunaan a JdbcDeviceDao
ketika secara eksplisit menentukannya dengan @Qualifier
penjelasan.
Apa yang sudah saya coba:
Saya mencoba mengatur properti
autowire-candidate="false"
dalam konfigurasi bean untuk JdbcDeviceDao:
<bean id="jdbcDeviceDao" class="com.initech.service.dao.jdbc.JdbcDeviceDao" autowire-candidate="false">
<property name="dataSource" ref="jdbcDataSource"/>
</bean>
karena dokumentasi Spring mengatakan itu
Menunjukkan apakah kacang ini harus dipertimbangkan saat mencari kandidat yang cocok untuk memenuhi persyaratan autowiring kacang lain. Perhatikan bahwa ini tidak mempengaruhi referensi eksplisit berdasarkan nama, yang akan diselesaikan bahkan jika kacang yang ditentukan tidak ditandai sebagai kandidat autowire. *
yang saya tafsirkan bahwa saya masih bisa melakukan autowire JdbcDeviceDao
menggunakan @Qualifier
anotasi dan memiliki HibernateDeviceDao
bean sebagai default. Rupanya interpretasi saya tidak benar, karena ini menghasilkan pesan kesalahan berikut saat memulai server:
Ketergantungan jenis [class com.sevenp.mobile.samplemgmt.service.dao.jdbc.JdbcDeviceDao]: diharapkan setidaknya 1 kacang yang cocok
berasal dari kelas tempat saya mencoba melakukan autowiring kacang dengan kualifikasi:
@Autowired
@Qualifier("jdbcDeviceDao")
Larutan:
saran skaffman untuk mencoba anotasi @Resource berhasil. Jadi konfigurasinya memiliki autowire-kandidat disetel ke false untuk jdbcDeviceDao dan saat menggunakan jdbcDeviceDao saya merujuknya menggunakan anotasi @Resource (bukan @Qualifier):
@Resource(name = "jdbcDeviceDao")
private JdbcDeviceListItemDao jdbcDeviceDao;
sumber
Jawaban:
Saya sarankan menandai kelas Hibernate DAO dengan
@Primary
, yaitu (dengan asumsi Anda digunakan@Repository
padaHibernateDeviceDao
):@Primary @Repository public class HibernateDeviceDao implements DeviceDao
Dengan cara ini akan dipilih sebagai kandidat autowire default, tanpa perlu
autowire-candidate
di kacang lain.Selain itu, daripada menggunakan
@Autowired @Qualifier
, saya merasa lebih elegan digunakan@Resource
untuk memetik biji tertentu, yaitu@Resource(name="jdbcDeviceDao") DeviceDao deviceDao;
sumber
@Resource
anotasi, seperti yang juga saya sarankan.@Resource
dan@Qualifier
, terlepas dari fakta bahwa yang pertama relatif lebih baru daripada yang terakhir?Tentang apa
@Primary
?@Primary public class HibernateDeviceDao implements DeviceDao
Atau jika Anda ingin versi Jdbc Anda digunakan secara default:
<bean id="jdbcDeviceDao" primary="true" class="com.initech.service.dao.jdbc.JdbcDeviceDao">
@Primary
juga bagus untuk pengujian integrasi ketika Anda dapat dengan mudah mengganti kacang produksi dengan versi stub dengan memberi anotasi.sumber
primary=""
atribut tersedia sebelumnya. Cukup deklarasikanHibernateDeviceDao
dalam XML dan kecualikan dari pemindaian komponen / anotasi.Untuk Spring 2.5, tidak ada
@Primary
. Satu-satunya cara adalah menggunakan@Qualifier
.sumber
The use of @Qualifier will solve the issue. Explained as below example : public interface PersonType {} // MasterInterface @Component(value="1.2") public class Person implements PersonType { //Bean implementing the interface @Qualifier("1.2") public void setPerson(PersonType person) { this.person = person; } } @Component(value="1.5") public class NewPerson implements PersonType { @Qualifier("1.5") public void setNewPerson(PersonType newPerson) { this.newPerson = newPerson; } } Now get the application context object in any component class : Object obj= BeanFactoryAnnotationUtils.qualifiedBeanOfType((ctx).getAutowireCapableBeanFactory(), PersonType.class, type);//type is the qualifier id you can the object of class of which qualifier id is passed.
sumber
Alasan @Resource (name = "{your child class name}") berfungsi tetapi @Autowired terkadang tidak berfungsi adalah karena perbedaan Urutan pencocokannya
Urutan pencocokan
Jenis @Autowire , Qualifier, Name
Urutan pencocokan @Resource
Name, Type, Qualifier
Penjelasan lebih detail dapat ditemukan di sini:
Inject and Resource dan Autowired annotations
Dalam kasus ini, kelas anak berbeda yang diwarisi dari kelas induk atau antarmuka membingungkan @Autowire, karena mereka berasal dari tipe yang sama; Karena @Resource menggunakan Nama sebagai prioritas pencocokan pertama, ini berfungsi.
sumber