Seperti namanya, injeksi anotasi adalah untuk mewujudkan injeksi melalui anotasi. Anotasi umum yang terkait dengan musim semi dan injeksi termasuk autowired, sumber daya, kualifikasi, layanan, pengontrol, repositori, dan komponen.
Autowired adalah injeksi otomatis, secara otomatis menemukan kacang yang sesuai dari konteks pegas untuk menyuntikkan
Sumber daya digunakan untuk menentukan injeksi nama
Kualifikasi dan Autowired bekerja bersama untuk menentukan nama kacang
Layanan, pengontrol, dan repositori masing -masing menandai kelas sebagai kelas lapisan layanan, kelas lapisan pengontrol, dan kelas lapisan penyimpanan data. Saat konfigurasi anotasi pemindaian pegas, kelas -kelas ini akan ditandai untuk menghasilkan kacang.
Komponen adalah istilah umum. Kelas penandaan adalah komponen. Saat spring scan dan konfigurasi anotasi, kelas -kelas ini akan ditandai untuk menghasilkan kacang.
Musim semi mendukung beberapa metode anotasi untuk injeksi kacang -kacangan:
@Resource javax.annotation jsr250 (anotasi umum untuk java) @Inject javax.
Secara intuitif, @Autowired adalah anotasi yang disediakan oleh Spring, dan yang lainnya adalah anotasi bawaan oleh JDK sendiri, dan Spring juga mendukung anotasi ini. Tapi apa perbedaan antara ketiganya saat digunakan? Setelah menguji metode ini, penulis menemukan beberapa fitur menarik.
Perbedaannya dirangkum sebagai berikut:
1. @Autowired memiliki properti yang diperlukan, yang dapat dikonfigurasi sebagai false. Dalam hal ini, jika kacang yang sesuai tidak ditemukan, pengecualian tidak akan dilemparkan. @Inject dan @Resource tidak memberikan konfigurasi yang sesuai, jadi Anda harus menemukannya jika tidak, pengecualian akan dilemparkan.
2. @Autowired dan @Inject pada dasarnya sama, karena keduanya menggunakan autowiredAnnotationBeanPostProcessor untuk menangani injeksi ketergantungan. Tapi @Resource adalah pengecualian, yang menggunakan CommonAnnotationBeanPostProcessor untuk menangani injeksi ketergantungan. Tentu saja, keduanya adalah processor beanpost.
@Autowired dan @Inject - Default AutoWirired berdasarkan Jenis - AutoWirired dengan nama kualifikasi dapat secara eksplisit ditentukan melalui @Qualifier. - Jika autowired by type gagal (tidak ditemukan atau beberapa implementasi ditemukan), degenerat ke autowired dengan nama lapangan @resource - default autowired dengan nama lapangan - jika autowired dengan nama lapangan gagal, degenerat untuk autowired dengan tipe - autowired dengan nama kualifikasi dapat ditentukan secara eksplisit melalui @qualifier - jika autowired dengan kualifikasi gagal. Tetapi pada saat ini jika autowired dengan nama lapangan gagal, itu tidak akan lagi merosot menjadi autowired berdasarkan jenis.
Tips Nama yang Berkualitas vs nama kacang
Dalam desain musim semi, nama yang memenuhi syarat tidak setara dengan nama kacang, yang terakhir harus unik, tetapi yang pertama mirip dengan fungsi tag atau grup, mengklasifikasikan kacang tertentu. Itu dapat mencapai efek getBytag (grup). Untuk kacang yang dikonfigurasi XML, Anda dapat menentukan nama kacang melalui atribut ID (jika tidak ditentukan, nama kelas adalah huruf kecil secara default), dan nama kualifikasi ditentukan melalui tag:
<bean id = "lamborghini"> <valifier value = "luxury"/> <!-menyuntikkan ketergantungan apa pun yang diperlukan oleh kacang ini-> </bean>
Jika melalui anotasi, Anda dapat menentukan nama kualifikasi melalui anotasi @Qualifier, dan tentukan nama kacang melalui nilai @named atau @component (@service, @repository, dll.):
@Component ("Lamborghini") @qualifier ("Luxury") Lamborghini kelas publik mengimplementasikan mobil {}atau
@Component @named ("Lamborghini") @qualifier ("Luxury") Lamborghini kelas publik mengimplementasikan mobil {}Demikian pula, jika nama kacang tidak ditentukan, musim semi akan default ke huruf kecil di nama kelas (lamborghini => lamborghini).
3. Gunakan metode ketergantungan injeksi anotasi untuk dilakukan sebelum metode injeksi XML. Jika dua metode injeksi digunakan pada saat yang sama pada ketergantungan pada kacang yang sama, maka XML lebih disukai. Namun, saya tidak khawatir bahwa dependensi yang disuntikkan melalui anotasi tidak dapat menyuntikkan kacang yang dikonfigurasi dalam XML. Injeksi ketergantungan dilakukan setelah kacang terdaftar.
4. Metode Tipe AutoWirired saat ini (penulis menggunakan versi 3.2.3.release), AutoWiriredAnnotationBeanPostProcessor implementasi Spring memiliki "bug", yang berarti bahwa @Autowired dan @Inject memiliki jebakan (disebut lubang, bukan bug karena mereka tampaknya disengaja ...). Ini adalah bug yang berasal dari online dan juga alasan untuk menulis artikel di sini. Adegannya adalah sebagai berikut:
Ada definisi berikut di Application-ontext.xml:
<Versi XML = "1.0" encoding = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://www.w3.org/2001/xmls xmlns: aop = "http://www.springframework.org/schema/aop" xmlns: context = "http://www.springframework.org/schema/context" xmlns: util = "http:/schema/context" xmlns: util = "http:/schema.context" xmlns: uTil = "http:/schema.context" xmlns: util = "http:/schema" XSI: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring--3.0 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http:/www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util <Konteks: anotasi-konfigurasi /> <konteks: komponen-scan-package = "me.arganzheng.study" /> <util: constant id = "en" static-field = "me.arganzheng.study.spring.autowired.consants.danguage.en" /> uTil: constant = "JA" static-field = "me.arganzheng.study.spring.autowired.constants.jangage.jp" /> <util: constant id = "ind" static-field = "me.arganzheng.study.spring.Autowired.constants.danguage.ind" /Id: constant. " static-field = "me.arganzheng.study.spring.autowired.constants.danguage.pt" /> <util: constant id = "th" static-field = "me.arganzheng.study.spring.Autowired.constants.danguage.th" /<study: constant. static-field = "me.arganzheng.study.spring.autowired.constants.danguage.ar" /> <util: constant id = "en-rin" static-field = "Me.arganzheng.study.spring.Autowired.constants.danguage.en_rin" /> <"" "" ID = "ID =" "" ID = "ID =" " Key-Type = "java.lang.string" value-type = "java.lang.string"> <entry tey = "pt" value = "pt" /> <entry tey = "br" value = "pt" /> <entry tey = "jp" value = "ja" /> <entry tey = "ja" value = "ja" /> <Entry = "ind entry tey =" ja "value =" JA "Nilai" /> <Entry = "Nilai =" Nilai = "Nilai =" Nilai "JA" JA "JA" /> <ESTRY = "ID =" ID = "ID" ID = "ID" ID = "JA" JA "JA" JA " /> <" Nilai " /<" Nilai " /<ESTRY =" Nilai "JA" JA "JA" JA " value="ind" /> <entry key="en-rin" value="en-rIn" /> <entry key="in" value="en-rIn" /> <entry key="en" value="en" /> <entry key="gb" value="en" /> <entry key="th" value="th" /> <entry key="ar" value="ar" /> <entry key="eg" value="ar" /> </util: peta> </boy>
Konstanta yang diterapkan oleh bidang statis didefinisikan di kelas berikut:
paket saya.arganzheng.study.spring.autowired; konstanta antarmuka publik {bahasa antarmuka publik {public static final string en = "CommonConstants.lang_English"; string final statis publik jp = "commonconstants.lang_japanese"; string final statis publik ind = "CommonConstants.lang_indonesian"; string final public static pt = "CommonConstants.lang_portuguese"; string final statis publik tH = "CommonConstants.lang_Thai"; string final statis public en_rin = "CommonConstants.lang_English_india"; string final statis public AR = "CommonConstants.lang_ARABIC"; }}Maka jika kita mendeklarasikan ketergantungan dalam kode sebagai berikut:
Public Class AutoWiriredTest memperluas BASESPRINGTESTCase {@Autowired private Map <String, String> languagechangesmap; @Test public void testAutowired () {notnull (languagechangesmap); System.out.println (languagechangesmap.getClass (). GetsImplename ()); System.out.println (languagechangesmap); }}Coba tebak, sesuatu yang aneh terjadi!
Hasil operasi adalah sebagai berikut:
LinkedHashMap {en = CommonConstants.lang_English, ja = CommonConstants.lang_Japanese, ind = CommonConstants.lang_indonesian, pt = CommonConstants.lang_portuguese}}}}}}}}}}}}}}}}}}}} everkon.Artinya, peta
Serius: Tertangkap Pengecualian Saat Mengizinkan TestExecutionListener
[org.springframework.test.context.support.dependencyInpectionTestExecutionListener@5c51ee0a] untuk menyiapkan contoh tes [me.arganzheng.study.spring.autowired.AutowiredTest@6e301e0] org.spramework. 'Me.arganzheng.study.spring.autowired.AutowiredTest': Injeksi dependensi autowired gagal; Pengecualian bersarang adalah org.springframework.beans.factory.beanscreationexception: tidak dapat autowire field: java.util.map me.arganzheng.study.spring.spring.autowired.AutowiredTest.danguagechangsmap; Pengecualian bersarang adalah org.springframework.beans.factory.nosuchbeandefinitionException: tidak ada kacang kualifikasi tipe [java.lang.string] ditemukan untuk ketergantungan [peta dengan jenis nilai java.lang.string]: diharapkan setidaknya 1 kacang yang memenuhi syarat sebagai kandidat autowire untuk ketergantungan ini. Anotasi ketergantungan: {@org.springframework.beans.factory.annotation.Autowired (wajib = true)} ... ed oleh: org.springframework.beans.factory.noSuchbeandfinition exception: tidak ada nilai java. Bean yang memenuhi syarat sebagai kandidat autowire untuk ketergantungan ini. Anotasi ketergantungan: {@org.springframework.beans.factory.annotation.Autowired (wajib = true)} di org.springframework.beans.factory.support.defaultListableBeanFactory.raisenosuchbeDefinitionSception (defaultListLeBeAbeArtAndeAn6 org.springframework.beans.factory.support.defaultListableBeanFactory.Doresolvedependency (defaultListableBeanFactory.java:843) di org.springframework.beans.factory.support.defaultListableBeanFactory.resolvedependency (defaultListableBeanFactory.java:768) di org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor $ AutoWiriredFieldElement.Inject (AutoWiredAnnotationBeanPostProcessor.java:486) ... 28Saya men -debug dan menemukan bahwa itu memang bug di musim semi. Ada masalah dengan metode ini di DefaultListableBeanFactory:
Objek yang dilindungi doresolvedependency (DependencyDescriptor descriptor, class <?> Type, string beanName, atur <string> AutoWiriredBeanNames, typeConverter typeConverter) melempar beansException {lain jika (peta.class.isassignableFrom (type) && type.isInterface ()) {ISassignableFrom (type) && type.isInterface () descriptor.getMapKeyType (); if (keytype == null ||! string.class.isassignableFrom (keytype)) {if (descriptor.isRequired ()) {throw new fatalbeanException ("Tipe kunci [" + keyType + "] dari peta [" + type.getName () + "] harus ditetapkan ke [java.lang. } return null; } Class <?> ValueType = descriptor.getMapValuetype (); if (valueType == null) {if (descriptor.isRequired ()) {lempar fatalbeanException baru ("Tidak ada jenis nilai yang dinyatakan untuk peta [" + type.getName () + "]"); } return null; } Peta <String, Object> MatchingBeans = findAutowIrecandides (beanname, valueType, descriptor); if (matchingbeans.isempty ()) {if (descriptor.isrequired ()) {raisenosuchbeandefinitionException (valueType, "peta dengan jenis nilai" + valueType.getName (), deskriptor); } return null; } if (AutoWiredBeanNames! = null) {AutoWiriredBeanNames.Addall (MatchingBeans.Keyset ()); } return matchingbeans; } ...}Kuncinya adalah kalimat ini: peta
Serius: Tertangkap Pengecualian Saat Mengizinkan TestExecutionListener
[org.springframework.test.context.support.dependencyInpectionTestExecutionListener@9476189] untuk menyiapkan instance tes [Me.arganzheng.study.spring.autowired.autowiredtest@2d546e21] ... disebabkan oleh: Autowired.autowiredtest@2d546e21] ... disebabkan oleh: disebabkan oleh: org.springframework.beans.factory.nosuchbeandefinitionException: tidak ada kacang kualifikasi tipe [java.lang.string] ditemukan untuk ketergantungan [peta dengan jenis nilai java.lang.string]: diharapkan setidaknya 1 kacang yang memenuhi syarat sebagai kandidat autowire untuk ketergantungan ini. Anotasi ketergantungan: { @org.springframework.beans.factory.annotation.Autowired (wajib = true), @org.springframework.beans.factory.annotation.q dariual (value = languagechangesmap)} di org.springframework.beans.factory.support.defaultListableBeanFactory.raisenosuchbeandefinitionException (defaultListableBeanFactory.java:986) di org.springframework.beans.factory.support.defaultListableBeanFactory.Doresolvedependency (defaultListableBeanFactory.java:843) di org.springframework.beans.factory.support.defaultListableBeanFactory.resolvedependency (defaultListableBeanFactory.java:768) di org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor $ AutoWiriredFieldElement.Inject (AutoWiredAnnotationBeanPostProcessor.java:486) ... 28Setelah debugging, saya menemukan bahwa jalur eksekusi sama dengan nama Qualfie yang tidak ditentukan. Apakah Anda tidak menentukan nama kacang? Mengapa masih autowired berdasarkan jenis? Setelah melihat lebih dekat, saya tahu. Metode Doresolvedependency dari DefaultListableBeanFactory membuat perbedaan antara tipe terlebih dahulu:
Objek yang dilindungi Doresolvedependency (DependencyDescriptor Deskriptor, kelas <?> Type, string beanname, atur <string> AutoWiriredBeanNames, TypeConverter TypeConverter) melempar BeansException {objek nilai = getAutowIreCanderateSolver (). GetSuggestedvalue {descriptor); descriptor); if (value! = null) {if (value instanceof string) {string strval = resolveembeddedValue ((string) value); Beandefinition bd = (beanname! = Null && containsbean (beanname)? GetmergedBeandefinition (beanname): null); value = evalucyBeandefinitionString (strval, bd); } TypeConverter converter = (typeConverter! = Null? TypeConverter: getTypeConverter ()); return (descriptor.getfield ()! = null? converter.convertifnecary (nilai, tipe, descriptor.getfield ()): converter.convertifnecary (nilai, jenis, deskriptor.getMethodparameter ())); } if (type.isArray ()) {class <?> componentType = type.getComponentType (); Peta <String, Object> MatchingBeans = FindAutoWirecandidates (BeanName, ComponentType, Descriptor); if (matchingbeans.isempty ()) {if (descriptor.isrequired ()) {raisenosuchbeandefinitionException (componentType, "array" + componentType.getName (), deskriptor); } return null; } if (AutoWiredBeanNames! = null) {AutoWiriredBeanNames.Addall (MatchingBeans.Keyset ()); } TypeConverter converter = (typeConverter! = Null? TypeConverter: getTypeConverter ()); return converter.convertifnecessary (matchingbeans.values (), type); } else if (collection.class.isassignableFrom (type) && type.isInterface ()) {class <?> elementType = descriptor.getCollectionType (); if (elementType == null) {if (descriptor.isRequired ()) {lempar fatalbeanException baru ("Tidak ada jenis elemen yang dinyatakan untuk koleksi [" + type.getName () + "]"); } return null; } Peta <String, Object> MatchingBeans = FindAutoWirecandides (BeanName, ElementType, Descriptor); if (matchingbeans.isempty ()) {if (descriptor.isrequired ()) {raisenosuchbeandefinitionException (elementType, "koleksi" + elementType.getName (), deskriptor); } return null; } if (AutoWiredBeanNames! = null) {AutoWiriredBeanNames.Addall (MatchingBeans.Keyset ()); } TypeConverter converter = (typeConverter! = Null? TypeConverter: getTypeConverter ()); return converter.convertifnecessary (matchingbeans.values (), type); } else if (map.class.isassignableFrom (type) && type.isInterface ()) {class <?> keyType = descriptor.getMapKeyType (); if (keytype == null ||! string.class.isassignableFrom (keytype)) {if (descriptor.isRequired ()) {throw new fatalbeanException ("Tipe kunci [" + keyType + "] dari peta [" + type.getName () + "] harus ditetapkan ke [java.lang. } return null; } Class <?> ValueType = descriptor.getMapValuetype (); if (valueType == null) {if (descriptor.isRequired ()) {lempar fatalbeanException baru ("Tidak ada jenis nilai yang dinyatakan untuk peta [" + type.getName () + "]"); } return null; } Peta <String, Object> MatchingBeans = findAutowIrecandides (beanname, valueType, descriptor); if (matchingbeans.isempty ()) {if (descriptor.isrequired ()) {raisenosuchbeandefinitionException (valueType, "peta dengan jenis nilai" + valueType.getName (), deskriptor); } return null; } if (AutoWiredBeanNames! = null) {AutoWiriredBeanNames.Addall (MatchingBeans.Keyset ()); } return matchingbeans; } else {peta <String, Object> MatchingBeans = findAutoWirecandidates (beanname, type, descriptor); if (matchingbeans.isempty ()) {if (descriptor.isrequired ()) {raisenosuchbeandefinitionException (type, "", descriptor); } return null; } if (matchingbeans.size ()> 1) {string primaryBeanName = detectioneprimaryCandidate (pencocokan, deskriptor); if (primaryBeanName == null) {lempar nouniqueBeandefinitionException baru (type, matchingbeans.keyset ()); } if (AutoWiredBeanNames! = null) {AutoWiriredBeanNames.Add (primerBeanName); } return matchingbeans.get (primerBeanName); } // Kami memiliki satu pertandingan yang tepat. Map.entry <String, Object> Entry = MatchingBeans.entryset (). Iterator (). NEXT (); if (AutoWiriredBeanNames! = NULL) {AutoWiriredBeanNames.Add (Entry.getKey ()); } return entry.getValue (); }}Jika itu adalah array, koleksi atau peta, autowired berdasarkan jenis sesuai dengan jenis elemen di kelas koleksi (jenis peta menggunakan nilai). Mengapa begitu istimewa? Ternyata musim semi adalah untuk tujuan ini: memungkinkan Anda untuk menyuntikkan semua implementasi yang cocok sekali, yaitu, Anda dapat menyuntikkannya seperti ini:
@Autowired
Daftar Pribadi <RABS> MOBIL;
Jika mobil Anda memiliki banyak implementasi, itu akan disuntikkan dan tidak akan dilaporkan lagi
org.springframework.beans.factory.nosuchbeandefinitionException: Tidak ada kacang unik tipe [Me.arganzheng.study.spring.Autowired.car] didefinisikan: Kacang pencocokan tunggal yang diharapkan tetapi menemukan 2: [audi, toyota].
Namun, dalam kasus di atas, jika Anda menggunakan @resource, Anda tidak akan memiliki masalah ini:
Public Class AutoWiriredTest memperluas BASESPRINGTESTCase {@resource @qualifier ("languagechangesmap") peta pribadi <string, string> languagechangesmap; @Test public void testAutowired () {AssertNotnull (languagechangesmap); System.out.println (languagechangesmap.getClass (). GetsImplename ()); System.out.println (languagechangesmap); }}Operasi Normal:
LinkedHashMap {pt = pt, br = pt, jp = ja, ja = ja, ind = ind, id = ind, en-rin = en-rin, in = en-rin, en = en, gb = en, th = th, ar = ar, misalnya = ar} Tentu saja, jika Anda tidak menentukan @qualifier ("languagechangesmap") dan nama lapangan bukan languagechangesmap, maka kesalahan yang sama masih akan dilaporkan.
Disebabkan oleh: org.springframework.beans.factory.nosuchbeandefinitionException: Tidak ada kacang kualifikasi tipe [java.lang.string] ditemukan untuk ketergantungan [peta dengan jenis nilai java.lang.string]: diharapkan setidaknya 1 kacang yang memenuhi syarat sebagai kandidat autowire untuk ketergantungan ini. Anotasi Dependensi: {@javax.annotation.Resource (shareable = true, mappedName =, description =, name =, type = class java.lang.object, authenticationType = container, lookup =)} at org.springframework.beans.factory.support.defaultListableBeanFactory.raisenosuchbeandefinitionException (defaultListableBeanFactory.java:986) di org.springframework.beans.factory.support.defaultListableBeanFactory.Doresolvedependency (defaultListableBeanFactory.java:843) di org.springframework.beans.factory.support.defaultListableBeanFactory.resolvedependency (defaultListableBeanFactory.java:768) di org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.AutowirereSource (CommonAnnotationBeanPostProcessor.java:438) di org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource (CommonAnnotationBeanPostProcessor.java:416) di org.springframework.context.annotation.CommonAnnotationBeanPostProcessor $ ResourceElement.getResourCetoinject (CommonAnnotationBeanPostProcessor.java:550) di org.springframework.beans.factory.annotation.injectionmetadata $ injectedeLement.inject (injectionmetadata.java:150) di org.springframework.beans.factory.annotation.nectionMetadata.inject (incectionmetadata.jectory org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.PostProcessPropertyValues (CommonAnnotationBeanPostProcessor.java:303) ... 26Selain itu, @Resource juga dapat mengimplementasikan daftar di atas untuk menerima semua implementasi:
Public Class AutoWiriredTest memperluas BASESPRINGTESTCase {@resource @qualifier ("languagechangesmap") peta pribadi <string, string> languagechangesmap; @Resource Private List <barger> mobil; @Test public void testAutowired () {AssertNotnull (languagechangesmap); System.out.println (languagechangesmap.getClass (). GetsImplename ()); System.out.println (languagechangesmap); Assertnotnull (mobil); System.out.println (cars.getClass (). GetsImplename ()); System.out.println (mobil); }}Berjalan dengan benar:
LinkedHashMap {pt = pt, br = pt, jp = ja, ja = ja, ind = ind, id = ind, en-rin = en-rin, in = en-rin, en = en, gb = en, th = th, ar = ar, mis. Arraylist [me.arganzheng.study.spring.autowired.audi@579584da, me.arganzheng.study.spring.autowired.toyota@19453122]
Ini karena anotasi @Resource menggunakan prosesor CommonAnnotationBeanPostProcessor, yang bukan penulis yang sama dengan AutoWirirEnnotationBeanPostProcessor [/Smile]. Saya tidak akan menganalisisnya di sini. Siswa yang tertarik dapat membaca kode dan mempelajarinya sendiri.
Kesimpulan terakhir adalah sebagai berikut :
1. @Autowired dan @Inject
Autowired berdasarkan tipe dapat secara eksplisit ditentukan oleh @Qualifier (kelas non-pengumpul. Catatan: Tidak autowired dengan nama kacang!)
Jika autowired berdasarkan tipe gagal (tidak ditemukan atau beberapa implementasi ditemukan), mengalami degenerasi untuk di-autowired berdasarkan nama bidang (kelas non-pengumpulan)
2. @Resource
Default Autowired dengan nama bidang
Jika autowired dengan nama lapangan gagal, itu akan merosot menjadi autowired berdasarkan jenis
Autowired dengan nama kualifikasi dapat ditentukan secara eksplisit melalui @Qualifier
Jika autowired dengan nama kualifikasi gagal, itu akan merosot menjadi autowired dengan nama lapangan. Namun, jika autowired dengan nama lapangan gagal, itu tidak akan lagi merosot menjadi autowired berdasarkan jenis. Proyek uji disimpan di GitHub. Ini adalah proyek Maven standar. Siswa yang tertarik dapat mengkloningnya secara lokal untuk menjalankan tes.
Mengisi kembali
Seorang kolega menunjukkan bahwa ada hukuman dalam dokumen resmi musim semi yang bertentangan dengan hubungan saya:
Namun, meskipun Anda dapat menggunakan konvensi ini untuk merujuk pada kacang tertentu dengan nama, @Autowired pada dasarnya tentang injeksi yang digerakkan oleh tipe dengan kualifikasi semantik opsional. Ini berarti bahwa nilai -nilai kualifikasi, bahkan dengan fallback nama kacang, selalu memiliki semantik yang menyempit dalam set jenis kecocokan; Mereka tidak secara semantik mengekspresikan referensi ke ID kacang yang unik.
Dengan kata lain, bahkan jika @Autowired ditambahkan dengan anotasi @Qualifier, itu sebenarnya autowired berdasarkan jenis. @Qualifier hanyalah kualifikasi, hanya kondisi filter. Saya menindaklanjuti dengan kode dan menemukan bahwa ini memang masalahnya. Nama @qualifier ini yang dirancang oleh Spring tidak setara dengan nama kacang. Dia sedikit mirip dengan tag. Namun, jika tag ini unik, maka efeknya sebenarnya setara dengan nama kacang. Dalam hal implementasi, Spring First GetByType, dapatkan kandidat daftar, dan kemudian filter sesuai dengan nama kualifikasi.
Tentukan lamborghini lain, di sini ditentukan menggunakan @Qualifier:
paket saya.arganzheng.study.spring.autowired; Impor org.springframework.beans.factory.annotation.qalifier; impor org.springframework.stereotype.component; @Component @qualifier ("Luxury") Lamborghini kelas publik mengimplementasikan mobil {}Tentukan Rolls-Royce lain, di sini dengan sengaja ditentukan dengan @named:
paket saya.arganzheng.study.spring.autowired; impor javax.inject.named; impor org.springframework.stereotype.component; @Component @named ("Luxury") Public Class Rollsroyce mengimplementasikan mobil {} Uji mobil mewah dengan definisi yang disuntikkan:
paket saya.arganzheng.study.spring.autowired; impor statis junit.framework.assert.assertnotnull; impor java.util.list; impor saya.arganzheng.study.basespringtestcase; impor org.junit.test; impor org.springframework.beans.factory.annotation.Autowired; Impor org.springframework.beans.factory.annotation.qalifier; / ** * * @author zhengzhibin * */ kelas publik AutowiredTest memperluas BasespringTestCase {@autowired @qualifier ("Luxury") Daftar Pribadi <RABS> LuxuryCars; @Test public void testAutowired () {AssertNotnull (LuxuryCars); System.out.println (luxurycars.getclass (). GetsImplename ()); System.out.println (LuxuryCars); }}Hasil operasi adalah sebagai berikut:
Arraylist [me.arganzheng.study.spring.autowired.lamborghini@66b875e1, me.arganzheng.study.spring.autowired.rollsroyce@58433b76]
Suplemen: Mode Autowiring
Spring mendukung empat mode autowire. Saat menggunakan metode konfigurasi XML, Anda dapat menentukannya melalui atribut autowire.
TIDAK. (Default) Tidak ada autowiring. Referensi kacang harus ditentukan melalui elemen ref. Mengubah pengaturan default tidak disarankan untuk penyebaran yang lebih besar, karena menentukan kolaborator secara eksplisit memberikan kontrol dan kejelasan yang lebih besar. Hingga taraf tertentu, ia mendokumentasikan struktur suatu sistem. julukan. Autowiring dengan nama properti. Spring mencari kacang dengan nama yang sama dengan properti yang perlu diotomatisasi. Misalnya, jika definisi kacang diatur ke autowire dengan nama, dan berisi properti master (yaitu, ia memiliki metode setmaster (..)), Spring mencari definisi kacang bernama master, dan menggunakannya untuk mengatur properti. bytype. Memungkinkan properti untuk di -autowired jika tepat satu kacang dari jenis properti ada di dalam wadah. Jika ada lebih dari satu, pengecualian fatal dilemparkan, yang menunjukkan bahwa Anda tidak boleh menggunakan bytype autowiring untuk kacang itu. Jika tidak ada kacang yang cocok, tidak ada yang terjadi; Properti tidak diatur. konstruktor. Analog dengan bytype, tetapi berlaku untuk argumen konstruktor. Jika tidak ada satu kacang dari jenis argumen konstruktor dalam wadah, kesalahan fatal dinaikkan.
Jika Anda menggunakan anotasi @Autowired, @Inject atau @Resource, itu akan sedikit lebih rumit, dan akan ada proses degradasi yang gagal, dan kualifikasi diperkenalkan. Tetapi prinsip dasarnya sama.