@ सेवा की घोषणा को कहां रखा जाना चाहिए? इंटरफ़ेस या कार्यान्वयन?


133

मैं स्प्रिंग का उपयोग करके एक एप्लिकेशन विकसित कर रहा हूं। मुझे @Serviceएनोटेशन का उपयोग करना आवश्यक है । मेरे पास ServiceIऔर ServiceImplऐसा है ServiceImpl implements ServiceI। मैं यहाँ उलझन में हूँ कि मुझे @Serviceएनोटेशन कहाँ रखना चाहिए ।

क्या मुझे इंटरफ़ेस या कार्यान्वयन को एनोटेट करना चाहिए @Service? इन दोनों दृष्टिकोणों के बीच अंतर क्या हैं?


यह एक ऐसी ही पोस्ट का मेरा जवाब है: stackoverflow.com/questions/38618995/…
Agustí Sánchez

जवाबों:


140

मैंने इंटरफ़ेस में कभी भी @Component(या @Service, ...) नहीं डाला , क्योंकि इससे इंटरफ़ेस बेकार हो जाता है। मुझे क्यों समझाते हैं।

दावा 1: यदि आपके पास एक इंटरफ़ेस है तो आप इंजेक्शन बिंदु प्रकार के लिए उस इंटरफ़ेस का उपयोग करना चाहते हैं।

दावा 2: एक इंटरफ़ेस का उद्देश्य यह है कि यह एक अनुबंध को परिभाषित करता है जिसे कई कार्यान्वयनों द्वारा कार्यान्वित किया जा सकता है। दूसरी तरफ आप अपने इंजेक्शन बिंदु ( @Autowired) है। केवल एक इंटरफ़ेस और इसे लागू करने वाला केवल एक वर्ग, (IMHO) बेकार है, और YAGNI का उल्लंघन करता है ।

तथ्य: जब आप डालते हैं:

  • @Component(या @Service, ...) एक अंतरफलक पर,
  • कई वर्ग हैं जो इसे लागू करते हैं,
  • कम से कम दो वर्ग स्प्रिंग बीन्स बन जाते हैं, और
  • एक इंजेक्शन बिंदु है जो टाइप आधारित इंजेक्शन के लिए इंटरफ़ेस का उपयोग करता है,

तब आपको मिलेगा और NoUniqueBeanDefinitionException (या आपके पास पर्यावरण, प्रोफाइल या क्वालिफायर के साथ एक बहुत ही विशेष कॉन्फ़िगरेशन सेटअप है ...)

निष्कर्ष: यदि आप इंटरफ़ेस पर @Component(या @Service, ...) का उपयोग करते हैं तो आपको कम से कम दो में से एक का उल्लंघन करना होगा। इसलिए मुझे लगता है कि यह @Componentइंटरफ़ेस के स्तर पर रखने के लिए उपयोगी नहीं है (कुछ दुर्लभ परिदृश्यों को छोड़कर) ।


स्प्रिंग-डेटा-जेपीए रिपोजिटरी इंटरफेस कुछ अलग हैं


3
यह बहुत दिलचस्प है कि आप क्या लिखते हैं ... इसलिए सही तरीका क्या है? क्या यह अंतराफलक को एनोटेट नहीं कर रहा है और सेवा एनोटेशन को लागू कर रहा है? क्या स्प्रिंग अभी भी इंटरफ़ेस प्रकार का उपयोग करके स्वत: सहेजने में सक्षम है? इस पर आपका क्या जवाब है> stackoverflow.com/questions/12899372/…
corlaez

3
मेरा एक सवाल है, जब हमें केवल एक वर्ग इसे लागू करता है, तो हमें सेवा स्तर के लिए एक इंटरफ़ेस बनाने की आवश्यकता क्यों है? मैं कई परियोजनाओं को देखा है, वे नियंत्रक परत, ** सेवा परत ( servicInterface , serviceInterfaceImpl ), और भंडार परत
युबराज

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

1
@ युबाज, इंटरफेस जब जरूरत पड़ने पर बीन्स को लाइटवेट इंटरफेस-बेस्ड जेक प्रॉक्सिज बनाने की अनुमति देते हैं। जब कोई इंटरफ़ेस नहीं होता है, तो स्प्रिंग को एक प्रॉक्सी बनाने के लिए cglib का उपयोग करके बीन्स को उपवर्ग या संशोधित करना पड़ता है। @Transactionalऐसे उदाहरणों में से एक है जहां एक बीन के लिए एक प्रॉक्सी का उपयोग किया जाता है। AOP एक और एक है।
योरी एन।

1
भले ही कुछ समय आपके पास एक से अधिक कार्यान्वयन वर्ग नहीं होंगे, फिर भी मैं एक इंटरफ़ेस में अपने तरीकों की घोषणा करना पसंद करता हूं। एक साथी डेवलपर को यह जांचना आसान होगा कि कार्यान्वयन के साथ चिंता किए बिना केवल घोषणाओं और प्रलेखन को देखकर क्या सेवाएं उपलब्ध हैं।
HFSDev

32

मूल रूप से @Service , @Repository , @Component , आदि जैसे एनोटेशन वे सभी एक ही उद्देश्य से कार्य करते हैं:

एनोटेशन-आधारित कॉन्फ़िगरेशन और क्लासपैथ स्कैनिंग का उपयोग करते समय ऑटो-डिटेक्शन।

मेरे अनुभव से मैं हमेशा उपयोग कर रहा हूँ @Serviceइंटरफेस या सार वर्गों और जैसे एनोटेशन पर एनोटेशन @Componentऔर @Repositoryउनके क्रियान्वयन के लिए। @Componentएनोटेशन मैं उन वर्गों पर उपयोग कर रहा हूं जो मूल उद्देश्यों, सरल स्प्रिंग बीन्स परोसता है, इससे ज्यादा कुछ नहीं। @Repositoryएनोटेशन मैं DAOपरत में उपयोग कर रहा हूं , उदाहरण के लिए यदि मुझे डेटाबेस से संवाद करना है, तो कुछ लेनदेन आदि।

इसलिए मैं @Serviceकार्यक्षमता के आधार पर आपके इंटरफ़ेस को और अन्य परतों के साथ एनोटेट करने का सुझाव दूंगा ।


10
क्या आप बता सकते हैं कि एनोटेटिंग इंटरफेस और एनोटेटिंग कार्यान्वयन के बीच क्या अंतर हैं?
TheKojuEffect

27
से वसंत डॉक्स , "यह टिप्पणी कार्यान्वयन कक्षाएं classpath स्कैनिंग के माध्यम से स्वतः डिटेक्ट किए जाने के लिए अनुमति देता है @Component की विशेषज्ञता के रूप में कार्य करता," सुझाव दिया कि यह कार्यान्वयन वर्ग पर इस्तेमाल किया जा करने का इरादा है।
noboks

1
@ TheKojuEffect, यह पोस्ट विवरण बनाम एनोटेटिंग इंटरफेस के कार्यान्वयन में अंतर के बारे में बताती है - stackoverflow.com/questions/3120143/…
महेश

@ user3257644 बस ध्यान दें कि उस पोस्ट के उत्तरों द्वारा दिए गए सुझाव विशेष रूप से '@ ट्रेंसेक्शनल' एनोटेशन के संबंध में हैं, सामान्य रूप से सभी एनोटेशन नहीं।
जोनाथन

3
इंटरफेस पर @ सेवा का अनाउंसमेंट का कोई प्रभाव नहीं है, बस अन्य स्टीरियोटाइप एनोटेशन के रूप में। सभी स्टीरियोटाइप एनोटेशन को अमूर्त या ठोस कक्षाओं में रखा जाना चाहिए।
बिगफुट

13

मैं प्रयोग किया जाता है @Component, @Service, @Controllerऔर @Repositoryकेवल कार्यान्वयन वर्गों पर और इंटरफेस पर नहीं अपनी टिप्पणियों। लेकिन @Autowiredइंटरफेसेस के साथ एनोटेशन ने फिर भी मेरे लिए काम किया।


7

@ सेवा पर एनोटेशन डालने का अधिकार यह है कि यह एक संकेत देता है कि यह एक सेवा है। मुझे नहीं पता कि क्या कोई क्रियान्वयन वर्ग डिफ़ॉल्ट रूप से इस घोषणा को प्राप्त करेगा।

कॉन साइड यह है कि आप स्प्रिंग विशिष्ट एनोटेशन का उपयोग करके अपने इंटरफेस को एक विशिष्ट ढांचे यानी स्प्रिंग के साथ जोड़ रहे हैं। जैसा कि इंटरफेस को कार्यान्वयन से अलग किया जाना चाहिए, मैं आपके इंटरफ़ेस के किसी भी फ्रेमवर्क एनोटेशन या ऑब्जेक्ट पार्ट का उपयोग करने का सुझाव नहीं दूंगा।


1
मुझे लगता है कि हम सभी ने मजबूत युग्मन तर्क को कई बार सुना है, लेकिन याद रखें कि एनोटेशन जार के बिना मौजूद हो सकते हैं, इसलिए मूल रूप से जब तक आपका युग्म एनोटेशन पर होता है तब भी इसे डिकॉय किया जा सकता है।
नील्स बेच नील्सन

1

वसंत का एक लाभ सेवा (या अन्य) को आसानी से लागू करना है। इसके लिए, आपको इंटरफ़ेस पर एनोटेट करने और इस तरह से वैरिएबल घोषित करने की आवश्यकता है:

@Autowired
private MyInterface myVariable;

और नहीं :

@Autowired
private MyClassImplementationWhichImplementsMyInterface myVariable;

पहले मामले की तरह, आप उस पल से इंजेक्ट करने के लिए किस कार्यान्वयन को सक्रिय कर सकते हैं यह अद्वितीय है (केवल एक वर्ग इंटरफ़ेस को लागू करता है)। दूसरे मामले में, आपको अपने सभी कोड को फिर से फ़िल्टर करने की आवश्यकता है (नए वर्ग के कार्यान्वयन का दूसरा नाम है)। परिणामस्वरूप, एनोटेशन को यथासंभव इंटरफ़ेस पर होना चाहिए। इसके अलावा, JDK परदे के पीछे के लिए अच्छी तरह से अनुकूल हैं: वे बनाया और अनुप्रयोग स्टार्टअप पर Instantiated क्योंकि रनटाइम प्रकार अग्रिम द्वारा जाना जाता है, CGlib परदे के पीछे के विपरीत है।


4
"MyClassImplementationWhichImplementsMyInterface" LOL
inafalcao

आपको काम करने के लिए पहले उदाहरण के लिए इंटरफ़ेस पर एनोटेट करने की आवश्यकता नहीं है। आप @Serviceएक क्रियान्वयन के साथ एनोटेट कर सकते हैं और इंटरफ़ेस को स्वाइप कर सकते हैं । स्प्रिंग इस इंटरफ़ेस को लागू करने वाली किसी भी वस्तु की जाँच करेगा।
मार्को

1

मैं @Serviceआपकी कक्षा पर रखूँगा, लेकिन एनोटेशन के लिए एक पैरामीटर के रूप में इंटरफ़ेस का नाम डालूँगा

interface ServiceOne {}

@Service("ServiceOne")
class ServiceOneImpl implements ServiceOne{}

ऐसा करने से आप सभी लाभ प्राप्त कर सकते हैं और फिर भी इंटरफ़ेस को इंजेक्ट कर सकते हैं लेकिन कक्षा प्राप्त कर सकते हैं

@Autowired 
private ServiceOne serviceOne;

इसलिए आपका इंटरफ़ेस स्प्रिंग फ्रेमवर्क से जुड़ा नहीं है और आप किसी भी समय क्लास बदल सकते हैं और अपने सभी इंजेक्शन पॉइंट्स को अपडेट नहीं करना है।

इसलिए यदि मैं कार्यान्वयन वर्ग को बदलना चाहता था तो मैं केवल नए वर्ग को एनोटेट कर सकता था और पहले से हटा सकता था लेकिन यह सब बदलना आवश्यक है। यदि आप कक्षा को इंजेक्ट करते हैं तो आपके पास बहुत सारे काम हो सकते हैं जब आप कभी भी अंतर्निहित वर्ग को बदलना चाहते हैं।


-1

सीधे शब्दों में:

@ सेवा सेवा परत के लिए एक स्टीरियोटाइप एनोटेशन है ।

@Repository के लिए एक स्टीरियोटाइप एनोटेशन है हठ परत।

@Component एक सामान्य स्टीरियोटाइप एनोटेशन है, जिसका उपयोग स्प्रिंग को एप्लिकेशन के संदर्भ में ऑब्जेक्ट का एक उदाहरण बनाने के लिए किया जाता है। उदाहरण के लिए किसी भी नाम को परिभाषित करना संभव है, डिफ़ॉल्ट है ऊंट मामले के रूप में वर्ग का नाम।


3
इन एनोटेशन का अर्थ खोजा नहीं जा रहा है, लेकिन इन्हें इंटरफ़ेस या इसके कार्यान्वयन पर लगाने के लिए कहाँ है।
नैनोसॉफ्ट

-3

5 एनोटेशन हैं जिनका उपयोग स्प्रिंग बीन्स बनाने के लिए किया जा सकता है। उत्तरों के नीचे सूची दें।

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

@ रिपोसिटरी - अपने डाओ लेयर क्लासेस को इंजेक्ट करने के लिए उपयोग करें।

@ सेवा - अपनी सेवा परत कक्षाओं को इंजेक्ट करने के लिए उपयोग करें। सेवा परत में भी आपको db लेनदेन प्रबंधन के लिए @Transactional एनोटेशन का उपयोग करने की आवश्यकता हो सकती है।

@ कंट्रोलर - अपने फ्रंटएंड लेयर कंट्रोलर्स के लिए उपयोग करें, जैसे कि जेएसएफ प्रबंधित बीन्स स्प्रिंग स्प्रिंग के रूप में इंजेक्ट करते हैं।

@ रेस्टकंट्रोलर - स्प्रिंग रेस्ट कंट्रोलर्स के लिए उपयोग करें, इससे आपको अपने बाकी तरीकों में @ResponseBody और @RequestBody एनोटेशन लगाने से हर बार बचने में मदद मिलेगी।

@Component - किसी भी अन्य मामले में इसका उपयोग करें जब आपको स्प्रिंग बीन को इंजेक्ट करने की आवश्यकता होती है जो नियंत्रक, सेवा या डेओ क्लास नहीं है


हां, आपको अपनी परतों (जैसे डेटा एक्सेस लेयर और सर्विस लेयर) की सीमाओं पर एक इंटरफ़ेस की आवश्यकता होती है। वे मॉड्यूल के ढीले युग्मन को सक्षम करते हैं जिसमें उन परतों के कार्यान्वयन होते हैं। उनके बिना, उल्लेखित परतों के ग्राहकों को ठोस प्रकारों को जानना होगा और जब आप कहेंगे, तो उन्हें बदलने की जरूरत है, कैशिंगडाओ के साथ अपने बेसिकडॉ को सजाने के लिए ...
Igand
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.