ตามชื่อที่แนะนำการฉีดคำอธิบายประกอบคือการตระหนักถึงการฉีดผ่านคำอธิบายประกอบ คำอธิบายประกอบทั่วไปที่เกี่ยวข้องกับฤดูใบไม้ผลิและการฉีดรวมถึง AutoWired, Resource, Qualifier, Service, Controller, ที่เก็บและส่วนประกอบ
AutoWired เป็นการฉีดอัตโนมัติโดยอัตโนมัติจะพบถั่วที่เหมาะสมจากบริบทของฤดูใบไม้ผลิเพื่อฉีดโดยอัตโนมัติ
ทรัพยากรใช้เพื่อระบุการฉีดชื่อ
รอบคัดเลือกและทำงานร่วมกันเพื่อระบุชื่อถั่ว
บริการคอนโทรลเลอร์และที่เก็บตามลำดับทำเครื่องหมายคลาสเป็นคลาสเลเยอร์บริการคลาสเลเยอร์คอนโทรลเลอร์และคลาสเลเยอร์การจัดเก็บข้อมูล เมื่อการกำหนดค่าคำอธิบายประกอบการสแกนสปริงคลาสเหล่านี้จะถูกทำเครื่องหมายเพื่อสร้างถั่ว
ส่วนประกอบเป็นคำทั่วไป การทำเครื่องหมายคลาสเป็นส่วนประกอบ เมื่อการสแกนสปริงและการกำหนดค่าคำอธิบายประกอบคลาสเหล่านี้จะถูกทำเครื่องหมายเพื่อสร้างถั่ว
ฤดูใบไม้ผลิรองรับวิธีการเพิ่มความคิดเห็นหลายวิธีสำหรับการฉีดพึ่งพาถั่ว:
@Resource javax.annotation JSR250 (คำอธิบายประกอบทั่วไปสำหรับ Java) @Inject Javax.Inject JSR330 (การฉีดพึ่งพาสำหรับ Java) @autowired org.springframework.bean.factory Spring Spring.factory Spring สปริง
@autowired เป็นคำอธิบายประกอบที่จัดทำโดยฤดูใบไม้ผลิและอื่น ๆ เป็นคำอธิบายประกอบในตัวโดย JDK เองและฤดูใบไม้ผลิยังรองรับคำอธิบายประกอบเหล่านี้ แต่อะไรคือความแตกต่างระหว่างทั้งสามนี้เมื่อใช้? หลังจากทดสอบวิธีการแล้วผู้เขียนพบคุณสมบัติที่น่าสนใจ
ความแตกต่างถูกสรุปดังนี้:
1. @autowired มีคุณสมบัติที่จำเป็นซึ่งสามารถกำหนดค่าเป็นเท็จ ในกรณีนี้หากไม่พบถั่วที่สอดคล้องกันข้อยกเว้นจะไม่ถูกโยนทิ้ง @Inject และ @Resource ไม่ได้ให้การกำหนดค่าที่สอดคล้องกันดังนั้นคุณต้องค้นหาพวกเขามิฉะนั้นจะมีข้อยกเว้นจะถูกโยนทิ้ง
2. @autowired และ @inject นั้นเหมือนกันเพราะทั้งคู่ใช้ AutoWiredannotationBeanPostProcessor เพื่อจัดการการฉีดพึ่งพา แต่ @Resource เป็นข้อยกเว้นซึ่งใช้ CommonAnnotationBeanPostProcessor เพื่อจัดการการฉีดพึ่งพา แน่นอนว่าทั้งคู่เป็น beanpostprocessors
@autowired และ @Inject - เริ่มต้นโดยอัตโนมัติตามประเภท - AutoWired โดยชื่อผู้คัดเลือกสามารถระบุได้อย่างชัดเจนผ่าน @qualifier - หากพบว่าเป็นแบบอัตโนมัติ (ไม่พบการใช้งานหลายครั้ง) ให้ degenerates เป็น autowired โดยชื่อฟิลด์ @Resource - เริ่มต้นโดยอัตโนมัติโดยชื่อฟิลด์ - หากชื่อฟิลด์โดยอัตโนมัติล้มเหลว แต่ในเวลานี้หากชื่อฟิลด์โดยอัตโนมัติล้มเหลวมันจะไม่เสื่อมสภาพเป็นประเภทโดยอัตโนมัติอีกต่อไป
เคล็ดลับชื่อที่ผ่านการรับรองเทียบกับชื่อถั่ว
ในการออกแบบฤดูใบไม้ผลิชื่อที่ผ่านการรับรองไม่เทียบเท่ากับชื่อถั่วหลังจะต้องไม่ซ้ำกัน แต่อดีตนั้นคล้ายกับฟังก์ชั่นของแท็กหรือกลุ่มการจำแนกถั่วเฉพาะ มันสามารถบรรลุผลของ getByTag (กลุ่ม) สำหรับถั่วที่กำหนดค่า XML คุณสามารถระบุชื่อถั่วผ่านแอตทริบิวต์ ID (หากไม่ได้ระบุชื่อคลาสจะเป็นตัวพิมพ์เล็กโดยค่าเริ่มต้น) และชื่อวุฒิการศึกษาจะถูกระบุผ่านแท็ก:
<bean id = "lamborghini"> <qualifier value = "Luxury"/> <!-ฉีดการพึ่งพาที่ต้องการโดยถั่วนี้-> </ebean>
หากผ่านคำอธิบายประกอบคุณสามารถระบุชื่อคุณสมบัติผ่านคำอธิบายประกอบ @qualifier และระบุชื่อถั่วผ่านค่าของ @Named หรือ @Component (@Service, @Repository ฯลฯ ):
@component ("Lamborghini") @qualifier ("หรูหรา") คลาสสาธารณะ Lamborghini ใช้รถยนต์ {}หรือ
@component @named ("Lamborghini") @qualifier ("หรูหรา") ชั้นเรียนสาธารณะ Lamborghini ใช้รถยนต์ {}ในทำนองเดียวกันหากไม่ได้ระบุชื่อถั่วสปริงจะเริ่มต้นเป็นตัวพิมพ์เล็กในชื่อคลาส (Lamborghini => Lamborghini)
3. ใช้วิธีการพึ่งพาการฉีด anotation เพื่อดำเนินการก่อนวิธีการฉีด XML หากมีการใช้วิธีการฉีดสองวิธีในเวลาเดียวกันกับการพึ่งพาถั่วเดียวกันนั้นก็เป็นที่ต้องการ XML อย่างไรก็ตามฉันไม่กังวลว่าการพึ่งพาที่ถูกฉีดผ่าน anotation ไม่สามารถฉีดถั่วที่กำหนดค่าใน XML การฉีดพึ่งพาจะดำเนินการหลังจากลงทะเบียนถั่ว
4. วิธีการที่อัตโนมัติโดยวิธีการพิมพ์ (ผู้เขียนใช้รุ่น 3.2.3.-release), การใช้งาน AutoWiredannotationBeanPostProcessor ของ Spring มี "ข้อบกพร่อง" ซึ่งหมายความว่า @autowired และ @inject มีข้อผิดพลาด (เรียกว่าหลุมไม่ใช่ข้อบกพร่อง นี่คือข้อผิดพลาดที่มาจากออนไลน์และยังเป็นเหตุผลในการเขียนบทความที่นี่ ฉากมีดังนี้:
มีคำจำกัดความต่อไปนี้ใน Application-context.xml:
<xml version = "1.0" การเข้ารหัส = "utf-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns: xsi = "http://ww.w3.org/2001/xml xmlns: aop = "http://www.springframework.org/schema/aop" xmlns: บริบท = "http://www.springframework.org/schema/contex XSI: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://ww.springframework http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework <บริบท: Annotation-config /> <บริบท: Component-scan base-base-package = "me.arganzheng.study" /> <util: ide id = "en" คงที่ field = "me.arganzheng.study.spring.autowired.constants.language.en" Static-field = "me.arganzheng.study.spring.autowired.constants.language.jp" /> <util: ide id = "ind" static-field = "me.arganzheng.study.spring.autowired.constants.language.ind" /> Static-field = "me.arganzheng.study.spring.autowired.constants.language.pt" /> <util: ide id = "th" คงที่ field = "me.arganzheng.study.spring.autowired.constants.language.th" /> Static-field = "me.arganzheng.study.spring.autowired.constants.language.ar" /> <util: id id = "en-rin" คงที่ field = "me.arganzheng.Sudy.spring.autowired.constants.language.en_rin key-type = "java.lang.string" value-type = "java.lang.string"> <entry key = "pt" value = "pt" /> <entry key = "br" value = "pt" /> <entry key = "jp" value = "ja" /> key = "id" 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" /> </util: แผนที่> </epeans>
ค่าคงที่ที่ใช้โดยสนามคงที่ถูกกำหนดในคลาสต่อไปนี้:
แพ็คเกจ me.arganzheng.study.spring.autowired; ค่าคงที่ส่วนต่อประสานสาธารณะ {ภาษาส่วนต่อสาธารณะสาธารณะ {สตริงสุดท้ายคงที่ en = "CommonConstants.lang_english"; สตริงสุดท้ายคงที่ JP = "CommonConstants.lang_japanese"; สตริงสุดท้ายคงที่สาธารณะ ind = "CommonConstants.lang_indonesian"; สตริงสุดท้ายคงที่สาธารณะ pt = "CommonConstants.lang_portuguese"; สตริงสุดท้ายคงที่ th = "CommonConstants.lang_thai"; สตริงสุดท้ายคงที่สาธารณะ en_rin = "CommonConstants.lang_english_india"; สตริงสุดท้ายคงที่สาธารณะ ar = "CommonConstants.lang_arabic"; -ถ้าเราประกาศการพึ่งพาในรหัสดังนี้:
คลาสสาธารณะ AutoWiredTest ขยาย BasesPringTestCase {@AutoWired MAP ส่วนตัว <String, String> LanguageChangesMap; @Test โมฆะสาธารณะ testautowired () {notnull (languageChangesMap); System.out.println (languageChangesmap.getClass (). getSimplename ()); System.out.println (LanguageChangesMap); -เดาว่ามีอะไรแปลก ๆ เกิดขึ้น!
ผลการดำเนินการมีดังนี้:
LinkedHashMap {en = CommonConstants.lang_english, ja = CommonConstants.lang_japanese, ind = Commonconstants.lang_indonesian, pt = Commonconstants.lang_portuguese, th = Commonconstants.lang_thai, ar = Commonconstants.lang_arabicกล่าวคือแผนที่
จริงจัง: จับข้อยกเว้นในขณะที่อนุญาตให้ testexecutionListener
[org.springframework.test.context.support.dependencteNuchentTestexecutionListener@5c51ee0a] เพื่อเตรียมอินสแตนซ์ทดสอบ [me.arganzheng.study.spring.autowired.autowiredtest@6e301e0] org.springframework 'me.arganzheng.study.spring.autowired.autowiredTest': การฉีดการพึ่งพาอัตโนมัติล้มเหลว; ข้อยกเว้นที่ซ้อนกันคือ org.springframework.beans.factory.beancreationexception: ไม่สามารถ AutoWire Field: Private Java.util.pap me.arganzheng.study.spring.autowired.autowiredTest.LanguageChangesmap; ข้อยกเว้นที่ซ้อนกันคือ org.springframework.beans.factory.nosuchbeandefinitionexception: ไม่มีถั่วที่มีคุณสมบัติตามประเภท [java.lang.string] พบการพึ่งพา [แผนที่ที่มีค่า java.lang.string] คำอธิบายประกอบการพึ่งพา: {@org.springframework.beans.factory.annotation.autowired (จำเป็น = จริง)} ... ed โดย: org.springframework.beans.factory.nosuchbeandefinitionexception ถั่วซึ่งมีคุณสมบัติเป็นผู้สมัคร AutoWire สำหรับการพึ่งพานี้ คำอธิบายประกอบการพึ่งพา: {@org.springframework.beans.factory.annotation.autowired (จำเป็น = จริง)} ที่ org.springframework.beans.factory.support.defaultlistablebeanformatory.raisenosuchebeandefinitionexception org.springframework.beans.factory.support.defaultlistablebeanfactory.doresolvedency (defaultlistablebeanfactory.java:843) ที่ org.springframework.beans.factory.support.defaultlistablebeanbeanbeanbeantive org.springframework.beans.factory.annotation.autowiredannotationbeanpostprocessor $ autowiredfieldelement.inject (AutoWiredannotationBeanPostProcessor.java:486) ... 28 เพิ่มเติมฉันดีบักและพบว่ามันเป็นข้อผิดพลาดในฤดูใบไม้ผลิ มีปัญหากับวิธีนี้ใน defaultlistablebeanfactory:
วัตถุที่ได้รับการป้องกัน doresolvedependency (descriptor rependencyDescriptor, คลาส <?> ประเภท, สตริง beanname, ตั้งค่า <string> AutoWiredBeanNames, typeconverter typeconverter) พ่น beansexception {... อื่น ๆ ถ้า (map.class.isassignablefrom (type) && type.isinterface if (keyType == null ||! string.class.isassignableFrom (keyType)) {ถ้า (descriptor.isrequired ()) {โยน fatalBeanException ใหม่ ("ประเภทคีย์ [" + keyType + "] ของแผนที่ [" } return null; } คลาส <?> valuetype = descriptor.getMapValUetype (); if (valueType == null) {ถ้า (descriptor.isrequired ()) {โยน fatalBeanException ใหม่ ("ไม่มีประเภทค่าที่ประกาศสำหรับแผนที่ [" + type.getName () + "]"); } return null; } แผนที่ <string, Object> MatchingBeans = findautowireCandidates (BeanName, ValueType, descriptor); if (matchingBeans.isEmpty ()) {ถ้า (descriptor.isrequired ()) {raisenosuchebeanDefinitionException (valueType, "แผนที่ที่มีค่าประเภท" + valueType.getName (), descriptor); } return null; } if (AutoWiredBeanNames! = null) {AutoWiredBeanNames.addall (MatchingBeans.keyset ()); } return matchingbeans; -กุญแจสำคัญคือประโยคนี้: แผนที่
จริงจัง: จับข้อยกเว้นในขณะที่อนุญาตให้ testexecutionListener
[org.springframework.test.context.support.dependencedinsurtestexecutionlistener@9476189] เพื่อเตรียมอินสแตนซ์ทดสอบ [me.arganzheng.study.spring.autowired.autowiredtest@2d546e21] ... org.springframework.beans.factory.nosuchbeandefinitionexception: ไม่มีถั่วที่มีคุณสมบัติเหมาะสม [java.lang.string] พบการพึ่งพา [แผนที่ที่มีค่าประเภท java.lang.string]: คาดว่าจะมีถั่วอย่างน้อย 1 คำอธิบายประกอบการพึ่งพา: { @org.springframework.beans.factory.annotation.autowired (จำเป็น = true), @org.springframework.beans.factory.annotation.qualifier (value = languagechangesmap)} ที่ org.springframework.beans.factory.support.defaultlistablebeanfactory.raisenosuchbeandefinitionexception (defaultlistablebeanfactory.java:986) ที่ org.springframework.beans.factory.support.defaultlistablebeanfactory.doresolvedency (defaultlistablebeanfactory.java:843) ที่ org.springframework.beans.factory.support.defaultlistablebeanbeanbeanbeantive org.springframework.beans.factory.annotation.autowiredannotationbeanpostprocessor $ autowiredfieldelement.inject (AutoWiredannotationBeanPostProcessor.java:486) ... 28 เพิ่มเติมหลังจากการดีบักฉันพบว่าเส้นทางการดำเนินการนั้นเหมือนกับชื่อ Qualfie ที่ไม่ได้ระบุ คุณไม่ได้ระบุชื่อถั่วเหรอ? เหตุใดจึงยังคงเป็นแบบอัตโนมัติ หลังจากมองใกล้ ๆ ฉันก็พบ วิธี Doresolvedependenc
วัตถุที่ได้รับการป้องกัน doresolvedependency (descriptor rependencyDescriptor, คลาส <?> ประเภท, สตริงถั่ว, ตั้งค่า <string> autoWiredBeanNames, typeconverter typeconverter) พ่น beansexception {ค่าวัตถุ = getAutowireCandidateresolver () if (value! = null) {if (ค่าอินสแตนซ์ของสตริง) {string strval = resolveembeddedValue ((สตริง)); beandefinition bd = (beanname! = null && containsbean (Beanname)? getMergedBeanDefinition (BeanName): NULL); value = EvaluateBeanDefinitionString (Strval, BD); } typeconverter converter = (typeconverter! = null? typeconverter: getTypeconverter ()); return (descriptor.getField ()! = null? converter.convertifneCENCYARY (ค่า, ประเภท, descriptor.getField ()): converter.ConvertifneSeCHE (ค่า, ประเภท, descriptor.getMethodParameter ()); } if (type.isarray ()) {class <?> componentYpe = type.getComponentYpe (); แผนที่ <string, Object> MatchingBeans = findautowirecandidates (Beanname, ComponentYpe, descriptor); if (matchingBeans.isEmpty ()) {ถ้า (descriptor.isrequired ()) {raisenosuchbeanDefinitionException (componentType, "อาร์เรย์ของ" + componentYpe.getName (), descriptor); } return null; } if (AutoWiredBeanNames! = null) {AutoWiredBeanNames.addall (MatchingBeans.keyset ()); } typeconverter converter = (typeconverter! = null? typeconverter: getTypeconverter ()); return converter.convertifnevey (matchingbeans.values (), type); } อื่นถ้า (collection.class.isassignableFrom (ประเภท) && type.isInterface ()) {คลาส <?> elementType = descriptor.getCollectionType (); if (elementType == null) {ถ้า (descriptor.isrequired ()) {โยน fatalBeanException ใหม่ ("ไม่มีประเภทองค์ประกอบที่ประกาศสำหรับการรวบรวม [" + type.getName () + "]"); } return null; } แผนที่ <string, Object> MatchingBeans = findautowirecandidates (Beanname, ElementType, descriptor); if (matchingBeans.isEmpty ()) {ถ้า (descriptor.isrequired ()) {raisenosuchebeanDefinitionException (ElementType, "คอลเลกชันของ" + elementType.getName (), descriptor); } return null; } if (AutoWiredBeanNames! = null) {AutoWiredBeanNames.addall (MatchingBeans.keyset ()); } typeconverter converter = (typeconverter! = null? typeconverter: getTypeconverter ()); return converter.convertifnevey (matchingbeans.values (), type); } อื่นถ้า (map.class.isassignableFrom (type) && type.isInterface ()) {คลาส <?> keyType = descriptor.getMapKeyType (); if (keyType == null ||! string.class.isassignableFrom (keyType)) {ถ้า (descriptor.isrequired ()) {โยน fatalBeanException ใหม่ ("ประเภทคีย์ [" + keyType + "] ของแผนที่ [" } return null; } คลาส <?> valuetype = descriptor.getMapValUetype (); if (valueType == null) {ถ้า (descriptor.isrequired ()) {โยน fatalBeanException ใหม่ ("ไม่มีประเภทค่าที่ประกาศสำหรับแผนที่ [" + type.getName () + "]"); } return null; } แผนที่ <string, Object> MatchingBeans = findautowireCandidates (BeanName, ValueType, descriptor); if (matchingBeans.isEmpty ()) {ถ้า (descriptor.isrequired ()) {raisenosuchebeanDefinitionException (valueType, "แผนที่ที่มีค่าประเภท" + valueType.getName (), descriptor); } return null; } if (AutoWiredBeanNames! = null) {AutoWiredBeanNames.addall (MatchingBeans.keyset ()); } return matchingbeans; } else {map <string, object> matchingBeans = findautowirecandidate (beanname, type, descriptor); if (matchingBeans.isEmpty ()) {ถ้า (descriptor.isrequired ()) {raisenosuchbeanDefinitionException (type, "", descriptor); } return null; } if (matchingBeans.Size ()> 1) {String primaryBeanName = deCinePrimaryCandidate (MatchingBeans, descriptor); if (primaryBeanName == null) {โยน nouniqueebeandefinitionException ใหม่ (ประเภท, matchingBeans.keyset ()); } if (autoWeiredBeanNames! = null) {autoWeiredBeanNames.add (primaryBeanName); } return matchingBeans.get (primaryBeanName); } // เรามีการแข่งขันหนึ่งรายการ map.entry <String, Object> entry = matchingBeans.entrySet (). iterator (). next (); if (AutoWiredBeanNames! = null) {autoWeiredBeanNames.add (entry.getKey ()); } return entry.getValue (); -หากเป็นอาร์เรย์คอลเลกชันหรือแผนที่โดยอัตโนมัติตามประเภทตามประเภทขององค์ประกอบในคลาสคอลเลกชัน (ประเภทของแผนที่ใช้ค่า) ทำไมถึงเป็นพิเศษ? ปรากฎว่าฤดูใบไม้ผลิมีจุดประสงค์นี้: ช่วยให้คุณสามารถฉีดการใช้งานทั้งหมดที่ตรงกับประเภทในครั้งเดียวนั่นคือคุณสามารถฉีดได้เช่นนี้:
@autowired
รายการส่วนตัว <SAR> รถยนต์;
หากรถของคุณมีการใช้งานหลายอย่างจะถูกฉีดและจะไม่ถูกรายงานอีกต่อไป
org.springframework.beans.factory.nosuchbeandefinitionexception: ไม่มีถั่วชนิดที่ไม่ซ้ำกัน [me.arganzheng.study.spring.autowired.car] ถูกกำหนดไว้
อย่างไรก็ตามในกรณีข้างต้นหากคุณใช้ @Resource คุณจะไม่มีปัญหานี้:
คลาสสาธารณะ AutoWiredTest ขยาย BasesPringTestCase {@Resource @qualifier ("languageChangesMap") แผนที่ส่วนตัว <สตริง, สตริง> languageChangesMap; @Test โมฆะสาธารณะ testautoWired () {assertNotNull (languageChangesMap); System.out.println (languageChangesmap.getClass (). getSimplename ()); System.out.println (LanguageChangesMap); -การทำงานปกติ:
LinkedHashMap {pt = pt, br = pt, jp = ja, ja = ja, ind = ind, id = ind, en-rin = en-rin, ใน = en-rin, en = en, gb = en, th = th, ar = ar, eg = ar}} แน่นอนถ้าคุณไม่ได้ระบุ @qualifier ("languageChangesMap") และชื่อฟิลด์ไม่ใช่ languageChangesMap จะยังคงมีการรายงานข้อผิดพลาดเดียวกัน
เกิดจาก: org.springframework.beans.factory.nosuchbeandefinitionexception: ไม่มีถั่วที่มีคุณสมบัติตามประเภท [java.lang.string] พบการพึ่งพา [แผนที่ที่มีค่า java.lang.string]: คาดว่าจะมีการพึ่งพาผู้สมัคร คำอธิบายประกอบการพึ่งพา: {@javax.annotation.resource (แบ่งปัน = true, mappedName =, คำอธิบาย =, name =, type = class java.lang.Object, AuthenticationType = container, lookup =)} ที่ org.springframework.beans.factory.support.defaultlistablebeanfactory.raisenosuchbeandefinitionexception (defaultlistablebeanfactory.java:986) ที่ org.springframework.beans.factory.support.defaultlistablebeanfactory.doresolvedency (defaultlistablebeanfactory.java:843) ที่ org.springframework.beans.factory.support.defaultlistablebeanbeanbeanbeantive org.springframework.context.annotation.CommonannotationBeanPostProcessor.Autowireresource (CommonannotationBeanPostProcessor.java:438) ที่ org.springframework.context.annotation.CommonannotationBeanPostProcessor.GetResource (CommonAnnotationBeanPostProcessor.java:416) ที่ org.springframework.context.annotation.CommonannotationBeanPostProcessor $ ResourceElement.getResourCetoInject org.springframework.beans.factory.annotation.injectametadata $ injectedelement.inject (Injectionmetadata.java:150) ที่ org.springframework.beans.factory.annot.injectametadata.inject org.springframework.context.annotation.CommonannotationBeanPostProcessor.postProcessPropertyValues (CommonannotationBeanPostProcessor.java:303) ... 26 เพิ่มเติมนอกจากนี้ @Resource ยังสามารถใช้รายการด้านบนเพื่อรับการใช้งานทั้งหมด:
คลาสสาธารณะ AutoWiredTest ขยาย BasesPringTestCase {@Resource @qualifier ("languageChangesMap") แผนที่ส่วนตัว <สตริง, สตริง> languageChangesMap; @Resource รายการส่วนตัว <AR> รถยนต์; @Test โมฆะสาธารณะ testautoWired () {assertNotNull (languageChangesMap); System.out.println (languageChangesmap.getClass (). getSimplename ()); System.out.println (LanguageChangesMap); assertNotNull (รถยนต์); System.out.println (cars.getClass (). getSimplename ()); System.out.println (รถยนต์); -ทำงานอย่างถูกต้อง:
LinkedHashMap {pt = pt, br = pt, jp = ja, ja = ja, ind = ind, id = ind, en-rin = en-rin, ใน = en-rin, en = en, gb = en, th = th, ar = ar, eg = ar} arraylist [me.arganzheng.study.spring.autowired.audi@579584da, me.arganzheng.study.spring.autowired.toyota@19453122]
นี่เป็นเพราะคำอธิบายประกอบ @Resource ใช้โปรเซสเซอร์ CommonAnnotationBeanPostProcessor ซึ่งไม่ใช่ผู้เขียนเดียวกับ AutoWiredAnnotationBeanPostProcessor [/Smile] ฉันจะไม่วิเคราะห์ที่นี่ นักเรียนที่สนใจสามารถอ่านรหัสและศึกษาด้วยตัวเอง
ข้อสรุปสุดท้ายมีดังนี้ :
1. @autowired และ @inject
AutoWired ตามประเภทสามารถระบุได้อย่างชัดเจนโดย @Qualifier (คลาสที่ไม่ใช่การรวบรวมหมายเหตุ: ไม่ได้รับการสอนโดย AutoWaire ด้วยชื่อถั่ว!)
หากพบว่าเป็นแบบอัตโนมัติโดยไม่พบ (ไม่พบการใช้งานหลายครั้ง) ให้ degenerates เป็น autoWired โดยชื่อฟิลด์ (คลาสที่ไม่ใช่การรวบรวม)
2. @Resource
เริ่มต้นโดยอัตโนมัติตามชื่อฟิลด์
หากชื่อฟิลด์โดยอัตโนมัติจะล้มเหลวมันจะเสื่อมสภาพเป็น AutoWired ตามประเภท
สามารถระบุชื่อคุณสมบัติได้อย่างชัดเจนผ่าน @qualifier
หากชื่อที่ผ่านการรับรองโดยอัตโนมัติจะล้มเหลวมันจะเสื่อมสภาพเป็นชื่อฟิลด์โดยอัตโนมัติ อย่างไรก็ตามหากชื่อฟิลด์โดยอัตโนมัติไม่สามารถลดลงได้อีกต่อไป โครงการทดสอบจะถูกบันทึกไว้ใน GitHub มันเป็นโครงการ Maven มาตรฐาน นักเรียนที่สนใจสามารถโคลนได้ในพื้นที่เพื่อทำการทดสอบ
เติมเต็ม
เพื่อนร่วมงานชี้ให้เห็นว่ามีประโยคในเอกสารทางการของฤดูใบไม้ผลิที่ขัดแย้งกับความสัมพันธ์ของฉัน:
อย่างไรก็ตามแม้ว่าคุณสามารถใช้การประชุมนี้เพื่ออ้างถึงถั่วที่เฉพาะเจาะจงตามชื่อ @autowired เป็นพื้นฐานเกี่ยวกับการฉีดชนิดที่ขับเคลื่อนด้วยชนิดที่มีคุณสมบัติทางความหมายเสริม ซึ่งหมายความว่าค่าคุณสมบัติแม้จะมีชื่อถั่วกลับมามีความหมายที่แคบลงภายในชุดการจับคู่ประเภท; พวกเขาไม่ได้แสดงความหมายเกี่ยวกับการอ้างอิงถึง ID ถั่วที่ไม่ซ้ำกัน
กล่าวอีกนัยหนึ่งแม้ว่า @autowired จะถูกเพิ่มด้วยคำอธิบายประกอบ @qualifier @qualifier เป็นเพียงผู้คัดเลือกเพียงเงื่อนไขตัวกรอง ฉันติดตามรหัสและพบว่านี่เป็นกรณีนี้ ชื่อ @qualifier นี้ออกแบบโดยฤดูใบไม้ผลิไม่เทียบเท่ากับชื่อถั่ว เขาค่อนข้างคล้ายกับแท็ก อย่างไรก็ตามหากแท็กนี้ไม่ซ้ำกันเอฟเฟกต์จะเทียบเท่ากับชื่อถั่ว ในแง่ของการดำเนินการสปริงแรก getBytype รับผู้สมัครรายชื่อจากนั้นกรองตามชื่อรอบคัดเลือก
กำหนด Lamborghini อื่นที่นี่มีการระบุโดยใช้ @qualifier:
แพ็คเกจ me.arganzheng.study.spring.autowired; นำเข้า org.springframework.beans.factory.annotation.qualifier; นำเข้า org.springframework.stereotype.component; @component @qualifier ("หรูหรา") คลาสสาธารณะ Lamborghini ใช้รถยนต์ {}กำหนด Rolls-Royce อื่นที่นี่มีการระบุอย่างจงใจด้วย @Named:
แพ็คเกจ me.arganzheng.study.spring.autowired; นำเข้า Javax.inject.named; นำเข้า org.springframework.stereotype.component; @Component @Named ("Luxury") Public Class Rollsroyce ใช้รถยนต์ {} ทดสอบรถหรูหราด้วยคำจำกัดความที่ฉีด:
แพ็คเกจ me.arganzheng.study.spring.autowired; นำเข้า Junit.framework.assert.assertNotNull; นำเข้า java.util.list; นำเข้า me.arganzheng.study.basespringtestcase; นำเข้า org.junit.test; นำเข้า org.springframework.beans.factory.annotation.autowired; นำเข้า org.springframework.beans.factory.annotation.qualifier; / ** * * @author Zhengzhibin * */ คลาสสาธารณะ AutoWiredTest ขยาย BasespringTestCase {@autowired @qualifier ("Luxury") รายการส่วนตัว <Car> LuyCarycars; @Test โมฆะสาธารณะ testautowired () {assertNotNull (LuyCarsars); System.out.println (luxurycars.getClass (). getSimplename ()); System.out.println (Luycars); -ผลการดำเนินการมีดังนี้:
arraylist [me.arganzheng.study.spring.autowired.lamborghini@66b875e1, me.arganzheng.study.spring.autowired.rollsroy@58433b76]
อาหารเสริม: โหมด AutoWiring
สปริงรองรับสี่โหมด AutoWire เมื่อใช้วิธีการกำหนดค่า XML คุณสามารถระบุได้ผ่านแอตทริบิวต์ AutoWire
เลขที่. (ค่าเริ่มต้น) ไม่มีการส่งอัตโนมัติ การอ้างอิงถั่วจะต้องกำหนดผ่านองค์ประกอบอ้างอิง การเปลี่ยนการตั้งค่าเริ่มต้นไม่แนะนำสำหรับการปรับใช้ที่ใหญ่ขึ้นเนื่องจากการระบุผู้ทำงานร่วมกันให้การควบคุมและความชัดเจนมากขึ้นอย่างชัดเจน ในระดับหนึ่งมันจัดทำเอกสารโครงสร้างของระบบ ชื่อ โดยอัตโนมัติตามชื่อคุณสมบัติ ฤดูใบไม้ผลิมองหาถั่วที่มีชื่อเดียวกับคุณสมบัติที่ต้องเป็นไปโดยอัตโนมัติ ตัวอย่างเช่นหากคำจำกัดความของถั่วถูกตั้งค่าเป็น AutoWire ตามชื่อและมีคุณสมบัติหลัก (นั่นคือมันมีเมธอด setmaster (.. )) สปริงจะมองหาคำจำกัดความของถั่วที่ชื่อมาสเตอร์และใช้เพื่อตั้งค่าคุณสมบัติ Bytype อนุญาตให้คุณสมบัติได้รับการอัตโนมัติหากถั่วหนึ่งชนิดของประเภทคุณสมบัติมีอยู่ในคอนเทนเนอร์ หากมีมากกว่าหนึ่งข้อยกเว้นที่ร้ายแรงจะถูกโยนลงไปซึ่งบ่งชี้ว่าคุณไม่สามารถใช้ bytype autoWiring สำหรับถั่วนั้น หากไม่มีถั่วที่ตรงกันจะไม่มีอะไรเกิดขึ้น ไม่ได้ตั้งค่าคุณสมบัติ ตัวสร้าง คล้ายคลึงกับ Bytype แต่นำไปใช้กับอาร์กิวเมนต์ตัวสร้าง หากไม่มีถั่วชนิดหนึ่งของประเภทอาร์กิวเมนต์คอนสตรัคเตอร์ในภาชนะบรรจุข้อผิดพลาดร้ายแรงจะถูกยกขึ้น
หากคุณใช้คำอธิบายประกอบ @AutoWired, @Inject หรือ @Resource มันจะซับซ้อนกว่าเล็กน้อยและจะมีกระบวนการย่อยสลายที่ล้มเหลวและมีการแนะนำรอบคัดเลือก แต่หลักการพื้นฐานเหมือนกัน