2015-03-16 9 views
6

मैं स्प्रिंग कोर प्रमाणीकरण के लिए अध्ययन कर रहा हूं और अध्ययन सामग्री सामग्री पर स्थापित इस प्रश्न के उत्तर से संबंधित कुछ संदेह हैं।क्यों वसंत में मुझे अंतिम श्रेणी को @ कॉन्फ़िगरेशन के साथ एनोटेट करने की अनुमति नहीं है?

तुम क्यों @Configuration

के साथ एक अंतिम वर्ग टिप्पणी करने की अनुमति नहीं है मेरे तर्क को पुष्ट करने के लिए एक निम्नलिखित इस दावे है:

निम्नलिखित विन्यास वर्ग पर विचार करें:

@Bean 
public AccountRepository accountRepository() { 
    return new JdbcAccountRepository(); 
} 

@Bean 
public TransferService transferService() { 
    TransferServiceImpl service = new TransferServiceImpl(); 
    service.setAccountRepository(accountRepository()); 
    return service; 
} 

@Bean 
public AccountService accountService() { 
    return new AccountServiceImpl(accountRepository()); 
} 

पहली बार यह स्थिति अजीब दिखाई दे सकती है क्योंकि पहली विधि (accountRepository()) एक सेम आईडी होने के रूप में एक JdbcAccountRepository वस्तु को दर्शाता है = AccountRepository कि, स्प्रिंग डिफ़ॉल्ट व्यवहार के बाद एक सिंगलटन

दूसरे और तीसरे विधि कॉल दो बार है अधिक समयखाता रिपोजिटरी() विधि जो दो बार जेडीबीसीएक्वाउंट रिपोजिटरी ऑब्जेक्ट्स को तुरंत चालू करना चाहिए और यह संभव नहीं है क्योंकि यह सिंगलटन है !!!

तो, यह स्थिति स्प्रिंग हल करने के लिए उपयोग करें वंशानुक्रम आधारित प्रॉक्सी रणनीति है कि मेरे विन्यास वर्ग (एक @Configuration द्वारा annoted) का एक बच्चा वर्ग बनाने की उम्मीद है और यह है करता है:

  • प्रत्येक सेम के लिए, एक उदाहरण के बच्चे कक्षा में कैश किया गया है

  • सी HILD वर्ग केवल पहले इन्स्टेन्शियशन

तो बच्चे को कक्षा प्रवेश बिंदु क्योंकि निम्न व्यवहार इस बच्चे वर्ग द्वारा कार्यान्वित किया जाता है पर सुपर कॉल:

सार्वजनिक वर्ग AppConfig $$ EnhancerByCGLIB $ फैली AppConfig {

public AccountRepository accountRepository() { 
    // if bean is in the applicationContext 
    // return bean 
    // else call super.accountRepository() and store bean in context 
} 

public TransferService transferService() { 
    // if bean is in the applicationContext, return bean 
    // else call super.transferService() and store bean in context 
} 

..................................................... 
..................................................... 
..................................................... 
} 

तो अगर मैं साथ अंतिम स्प्रिंग एक विन्यास वर्ग व्याख्या इस व्यवहार नहीं हो सकता है क्योंकि जावा एक अंतिम कक्षा में नहीं कर सकते

क्या यह सही है?

उसी तर्क का उपयोग करके मैं यह भी कह सकता हूं कि वसंत में मुझे @ बीन एनोटेशन के साथ एनोटेटेड अंतिम विधि नहीं हो सकती है?

क्योंकि, जैसा कि पिछले उदाहरण में दिखाया गया है, मुझे लगता है कि जब स्टार्टअप समय मेरे विन्यास वर्ग के बच्चे वर्ग (प्रॉक्सी) बनाई गई है होता है कि प्रत्येक सेम के लिए , एक उदाहरण के बच्चे कक्षा में कैश किया गया है और यदि यह अंतिम है तो यह संभव नहीं है (लेकिन मैं इस दावे के बारे में पूरी तरह से निश्चित नहीं हूं)

क्या मुझे कुछ याद आ रही है? क्या आप मुझे सही व्याख्या दे सकते हैं?

Tnx

उत्तर

7

स्प्रिंग @Configuration वर्गों के साथ एनोटेट कक्षाओं के लिए गतिशील प्रॉक्सी पैदा करता है। वसंत बनाने के लिए स्प्रिंग आपकी कक्षा का विस्तार करने के लिए CGLIB का उपयोग करता है। इसलिए, विन्यास कक्षाएं अंतिम नहीं हो सकती हैं।

के बारे में accountRepository() दो बार लागू किया जा रहा है:

आप accountRepository() विधि आह्वान तो एक उदाहरण बनाने के लिए है, यह कोई और अधिक एक स्प्रिंग कामयाब सेम है। वसंत को इस तरह से बनाए गए उदाहरणों का कोई विचार नहीं होगा। इसलिए, आप JdbcAccountRepository

के कई उदाहरण के साथ खत्म हो जाएगा अगर आप नीचे के रूप में कॉन्फ़िगर सिंगलटन व्यवहार की रक्षा कर सकते हैं: उपवर्गीकरण ठीक से काम करता

@Bean 
public TransferService transferService(JdbcAccountRepository jdbcAcctRepo) { 
    TransferServiceImpl service = new TransferServiceImpl(); 
    service.setAccountRepository(jdbcAcctRepo); 
    return service; 
} 

@Bean 
public AccountService accountService(JdbcAccountRepository jdbcAcctRepo) { 
    return new AccountServiceImpl(jdbcAcctRepo); 
} 
+2

असल में अगर, आप अन्य सेम विधियों (accountRepository की तरह (कॉल कर सकते हैं))। प्रॉक्सी तब निर्धारित करेगा कि क्या नया बीन इंस्टेंस बनाना आवश्यक है या यदि कोई पहले से मौजूद है। – dunni

+0

यदि कॉन्फ़िगरेशन क्लास अंतिम नहीं है, तो वसंत उप-वर्ग हो सकता है। और, 'accountRepository()' विधि आमंत्रण से संबंधित, वसंत को यह नहीं पता कि विधि के अंदर क्या हो रहा है। वसंत एक तर्क में हुक नहीं कर सकता है कि यह जांचने के लिए कि बीन पहले से ही बनाया गया है, हर बार 'नया' ऑपरेटर का उपयोग किया जाता है। – Mithun

+1

यहां तक ​​कि यह थोड़ा देर हो चुकी है, लेकिन मैं इस जवाब पर फिर से ठोकर खाई: बेशक वसंत नहीं देख सकता है खाते में क्या होता है रिपोजिटरी() विधि। लेकिन स्प्रिंग प्रॉक्सी खाते में सभी कॉल को रोक देगा, रिपोजिटरी() विधि स्वयं, और चेक करता है, अगर उस प्रकार का बीन पहले से मौजूद है और वर्तमान एप्लिकेशन संदर्भ में परिभाषित नाम है। यदि यह मामला है, तो प्रॉक्सी बीन लौटाता है (और विधि को निष्पादित नहीं करता है), यदि नहीं, वास्तविक विधि कहा जाता है और लौटा बीन अनुप्रयोग संदर्भ में संग्रहीत किया जाता है। यही कारण है कि एक विन्यास बीन में कई बार बीन निर्माण विधियों को कॉल करना सुरक्षित है – dunni

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

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