2010-04-26 12 views
23

जब autowiring@Autowire अजीब समस्या

मैं इस तरह एक समान कोड है मैं एक अजीब व्यवहार है, और इसे

@Controller 
public class Class1 { 
    @Autowired 
    private Class2 object2; 
    ... 
} 

@Service 
@Transactional 
public class Class2{ 
    ... 
} 

समस्या है काम करता है मैं की जरूरत है कि कि Class2 एक अंतरफलक को लागू करता है तो इस कोड को मैं एक org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type for Class2 पाने के साथ

@Controller 
public class Class1 { 
    @Autowired 
    private Class2 object2; 
    ... 
} 

@Service 
@Transactional 
public class Class2 implements IServiceReference<Class3, Long>{ 
    ... 
} 

public interface IServiceReference<T, PK extends Serializable> { 
    public T reference(PK id); 
} 

: मैं केवल Class2 तो अब यह पसंद है बदल दिया है। ऐसा लगता है कि @Transitional एनोटेशन इंटरफ़ेस के साथ संगत नहीं है क्योंकि अगर मैं @Transitional एनोटेशन या i mplements IServiceReference<Class3, Long> समस्या को अपमानित करता हूं और बीन इंजेक्शन दिया जाता है (हालांकि मुझे इस कक्षा में दोनों की आवश्यकता है)। यह तब भी होता है जब मैं कक्षा में बजाय विधियों में एनोटेशन @Transitional डालता हूं।

यदि यह मदद करता है तो मैं वसंत 3.0.2 का उपयोग करता हूं।

लेनदेन विधि के साथ इंटरफ़ेस को संगत नहीं है? क्या यह एक वसंत बग हो सकता है?

उत्तर

28

समस्या यह है कि आपके Class1 और IServiceReference के लिए एक संदर्भ की जरूरत है Class2

@Controller 
public class Class1 { 
@Autowired 
private IServiceReference object2; 
    ... 
} 

कारण यह है कि वसंत वर्गों है कि आप @Transactional चिह्नित के लिए एक गतिशील प्रॉक्सी पैदा कर रही है है की ठोस संदर्भ नहीं है। इस प्रकार जब क्लास 2 को प्रॉक्सी ऑब्जेक्ट में लपेटा जाता है जो स्पष्ट रूप से क्लास 2 टाइप नहीं होता है, लेकिन IServiceReference टाइप किया जाता है। मानक J2SE गतिशील प्रॉक्सी का उपयोग करने के

स्प्रिंग AOP चूक:

आप प्रॉक्सी समर्थन के साथ Class2 का उपयोग करने का व्यवहार चाहते हैं तो आप CGLIB चालू करने के लिए होगा नीचे पढ़ें:

स्प्रिंग्स डॉक्टर से एओपी प्रॉक्सी के लिए। यह किसी भी इंटरफ़ेस (या इंटरफेस का सेट) को प्रॉक्सी करने में सक्षम बनाता है।

वसंत एओपी CGLIB प्रॉक्सी का भी उपयोग कर सकता है। इंटरफेस के बजाय कक्षाओं, प्रॉक्सी के लिए यह आवश्यक है। यदि कोई व्यावसायिक ऑब्जेक्ट इंटरफ़ेस को लागू नहीं करता है तो CGLIB का उपयोग डिफ़ॉल्ट रूप से किया जाता है। चूंकि यह वर्गों की बजाय इंटरफेस करने के लिए कार्यक्रम के लिए अच्छा अभ्यास है, व्यवसाय कक्षा सामान्यतः एक या अधिक व्यावसायिक इंटरफेस लागू करेगा। यह उन (उम्मीद दुर्लभ) ऐसे मामलों में जहां आप जरूरत है एक विधि है कि एक इंटरफेस पर घोषित नहीं जाता है, या सलाह देने के लिए में, बल CGLIB के उपयोग के लिए संभव है, जहां आप जरूरत एक पद्धति के लिए एक प्रॉक्सी वस्तु पारित करने के लिए एक ठोस प्रकार के रूप में।

इस तथ्य को समझना महत्वपूर्ण है कि वसंत एओपी प्रॉक्सी-आधारित है। अनुभाग के लिए की पूरी तरह से जांच की वास्तव में का अर्थ है, अनुभाग अनुभाग 5.6.1, "एओपी प्रॉक्सी को समझना" देखें।

13

Transactional एनोटेशन वसंत का निर्देश एनोटेट सेम के आसपास प्रॉक्सी वस्तुओं उत्पन्न करने के लिए, लेन-देन संबंधी अर्थ विज्ञान लागू करने के लिए। उत्पन्न प्रॉक्सी लक्ष्य बीन के रूप में एक ही इंटरफेस को लागू करेगा। तो यदि आपका लक्ष्य बीन IServiceReference लागू करता है, तो जेनरेट प्रॉक्सी होगा।

यदि लक्ष्य बीन में कोई कार्यान्वित इंटरफेस नहीं है, तो जेनरेट प्रॉक्सी लक्ष्य बीन प्रकार के उपclass होगा।

आपके मूल उदाहरण में, लेनदेन संबंधी प्रॉक्सी Class2 का उप-वर्ग होगा, क्योंकि Class2 ने कोई इंटरफेस लागू नहीं किया था। जब आपने IServiceReference को लागू करने के लिए Class2 को बदल दिया, तो उत्पन्न प्रॉक्सी अब Class2 को बढ़ाया नहीं गया, और इसके बजाय IServiceReference लागू किया गया। इससे आपके ClassCastException का कारण बन गया।

इस स्थिति का सबसे अच्छा तरीका Class1 से Class2 पर संदर्भ को निकालना है, और इसके बजाय Class2 से पूरी तरह से अपने इंटरफेस के माध्यम से बात करना है। Class2 जितनी चाहें उतनी इंटरफेस को कार्यान्वित कर सकता है, प्रॉक्सी उन सभी को लागू करेगा।

आप इंटरफेस के बावजूद वसंत वसंत उत्पन्न करने के लिए स्प्रिंग को मजबूर कर सकते हैं, लेकिन यह अतिरिक्त जटिलता है, और मैं इसके खिलाफ अनुशंसा करता हूं।

+5

असल में वही बात मैंने कहा :) –

1

तुम भी this documentation देख

@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) 

जोड़कर प्रॉक्सी के लिए यह मजबूर कर सकते हैं।

+0

यह बिल्कुल आवश्यक है, जब कार्यान्वित इंटरफ़ेस वास्तव में घटकों के तारों से संबंधित नहीं है। ऐसा हो सकता है कि आप कहीं ऐसा पैरामीटर पैरामीटर के रूप में पास करना चाहते हैं, लेकिन इंटरफ़ेस के रूप में टाइप किया गया है। वसंत के साथ कुछ भी नहीं करना है। यदि कई इंटरफेस हैं, तो कोई समस्या नहीं है। यदि केवल एक है, वसंत की चीजें यह उसके लिए नौकरी है - और यह '@ स्कोप' पूरी तरह से अपने निर्धारण को ठीक करता है। :-) – virgo47

संबंधित मुद्दे