java - <संदर्भ: एनोटेशन-कॉन्फ़िगरेशन> बनाम<संदर्भ: घटक-स्कैन> के बीच अंतर




spring configuration (9)

मैं वसंत 3 सीख रहा हूं और मुझे <context:annotation-config> और <context:component-scan> पीछे कार्यक्षमता को समझना प्रतीत नहीं होता है।

जो मैंने पढ़ा है, उससे वे अलग-अलग एनोटेशन (@Required, @Autowired आदि बनाम @ कॉम्पोनेंट, @ रिपोजिटरी, @ सेवा आदि) को संभालने लगते हैं, लेकिन जो मैंने पढ़ा है उससे भी वे उसी बीन पोस्ट प्रोसेसर कक्षाओं को पंजीकृत करते हैं।

मुझे और भी भ्रमित करने के लिए, <context:component-scan> पर एक annotation-config विशेषता है।

क्या कोई इन टैग पर कुछ प्रकाश डाल सकता है? क्या समान है, क्या अलग है, एक दूसरे द्वारा छेड़छाड़ की जाती है, वे एक-दूसरे को पूरा करते हैं, क्या मुझे उनमें से एक की ज़रूरत है?


एक <context:component-scan/> कस्टम टैग जावा पैकेजों को स्कैन करने और क्लासपाथ से बीन परिभाषाओं को पंजीकृत करने की प्राथमिक ज़िम्मेदारी के अलावा, बीन परिभाषाओं के समान सेट को पंजीकृत करता है।

अगर किसी कारण से डिफ़ॉल्ट बीन परिभाषाओं के इस पंजीकरण से बचा जाना है, तो ऐसा करने का तरीका घटक-स्कैन में अतिरिक्त "एनोटेशन-कॉन्फ़िगरेशन" विशेषता निर्दिष्ट करना है, इस प्रकार:

<context:component-scan basePackages="" annotation-config="false"/>

संदर्भ: http://www.java-allandsundry.com/2012/12/contextcomponent-scan-contextannotation.html


दोनों के बीच का अंतर वास्तव में सरल है!

<context:annotation-config /> 

आपको एनोटेशन का उपयोग करने में सक्षम बनाता है जो केवल बीन्स के गुणों और कन्स्ट्रक्टरों को तारों तक सीमित कर देता है!

जहाँ तक

<context:component-scan base-package="org.package"/> 

सब कुछ सक्षम करता है जो <context:annotation-config /> कर सकते हैं, स्टीरियोटाइप जैसे .. .. @Component , @Service , @Repository @Service के उपयोग के साथ। तो आप पूरे सेम तार कर सकते हैं और केवल रचनाकारों या गुणों तक ही सीमित नहीं हैं!


वसंत आपको दो चीजें करने की अनुमति देता है:

  1. सेम की स्वचालन
  2. सेम की Autodiscovery

1. ऑटोवॉयरिंग
आमतौर पर applicationContext.xml में आप बीन्स परिभाषित करते हैं और अन्य बीन्स कन्स्ट्रक्टर या सेटर विधियों का उपयोग करके वायर्ड होते हैं। आप एक्सएमएल या एनोटेशन का उपयोग कर सेम तार कर सकते हैं। यदि आप एनोटेशन का उपयोग करते हैं, तो आपको एनोटेशन सक्रिय करने की आवश्यकता है और आपको applicationContext.xml में <context:annotation-config /> जोड़ना होगा। यह applicationContext.xml से टैग की संरचना को सरल बना देगा, क्योंकि आपको मैन्युअल रूप से बीन्स (कन्स्ट्रक्टर या सेटर) तार नहीं करना पड़ेगा। आप @Autowire एनोटेशन का उपयोग कर सकते हैं और बीन्स प्रकार के द्वारा @Autowire किया जाएगा।

मैन्युअल एक्सएमएल विन्यास से बचने के लिए एक कदम आगे है

2. Autodiscovery
Autodiscovery एक्सएमएल को एक कदम आगे सरलीकृत कर रहा है, इस अर्थ में कि आपको भी <bean> टैग को applicationContext.xml में जोड़ने की आवश्यकता नहीं है। आप केवल निम्नलिखित बीन्स में से एक के साथ विशिष्ट बीन्स को चिह्नित करते हैं और वसंत स्वचालित रूप से चिह्नित बीन्स और उनकी निर्भरताओं को वसंत कंटेनर में तारित कर देगा। टिप्पणियां निम्नानुसार हैं : @ नियंत्रक , @ सेवा , @ कॉम्पोनेंट , @ रिपोजिटरी<context:component-scan> का उपयोग करके और बेस पैकेज को इंगित करते हुए, वसंत स्प्रिंग कंटेनर में घटकों को स्वतः खोज और तार करेगा।

एक निष्कर्ष के रूप में:

  • <context:annotation-config /> का उपयोग @Autowired एनोटेशन का उपयोग करने में सक्षम होने के लिए किया जाता है
  • <context:component-scan /> विशिष्ट बीन्स की खोज और ऑटोवॉयरिंग के प्रयास को निर्धारित करने के लिए प्रयोग किया जाता है।

संदर्भ: एनोटेशन-config:

यह वसंत को बताता है कि मैं वसंत बीन एडीएन के रूप में एनोएटेड बीन्स का उपयोग करता हूं, जिन्हें वसंत कॉन्फ़िगर xml फ़ाइल में घोषित करने के बजाय @Autowired एनोटेशन के माध्यम से तारित किया जाएगा।

संदर्भ: घटक-स्कैन बेस-पैकेज = "com.test ...": यह स्प्रिंग कंटेनर को बताता है, जहां उन एनोटेटेड सेम खोजना शुरू करें। यहां वसंत के सभी उप पैकेजों की खोज होगी


<context:annotation-config> का उपयोग पहले से ही आवेदन संदर्भ में पंजीकृत बीन्स में एनोटेशन को सक्रिय करने के लिए किया जाता है (इससे कोई फर्क नहीं पड़ता कि उन्हें एक्सएमएल या पैकेज स्कैनिंग द्वारा परिभाषित किया गया था)।

<context:component-scan> क्या कर सकता है <context:annotation-config> करता है लेकिन <context:component-scan> एप्लिकेशन संदर्भ में बीन्स खोजने और पंजीकृत करने के लिए संकुल स्कैन भी करता है।

मैं अंतर / समानताओं को दिखाने के लिए कुछ उदाहरणों का उपयोग करूंगा।

चलिए B और C को A में इंजेक्शन के साथ टाइप A , B और C के तीन सेम के मूल सेटअप के साथ शुरू करते हैं।

package com.xxx;
public class B {
  public B() {
    System.out.println("creating bean B: " + this);
  }
}

package com.xxx;
public class C {
  public C() {
    System.out.println("creating bean C: " + this);
  }
}

package com.yyy;
import com.xxx.B;
import com.xxx.C;
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc; 
  }
}

निम्नलिखित एक्सएमएल विन्यास के साथ:

<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A">
  <property name="bbb" ref="bBean" />
  <property name="ccc" ref="cBean" />
</bean>

संदर्भ लोड करने से निम्नलिखित आउटपुट उत्पन्न होता है:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

ठीक है, यह अपेक्षित आउटपुट है। लेकिन यह "पुरानी शैली" वसंत है। अब हमारे पास एनोटेशन हैं इसलिए एक्सएमएल को सरल बनाने के लिए उन लोगों का उपयोग करें।

सबसे पहले, बीनबी और ccc गुणों को बीन A पर ऑटोवॉयर करने दें:

package com.yyy;
import org.springframework.beans.factory.annotation.Autowired;
import com.xxx.B;
import com.xxx.C;
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  @Autowired
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  @Autowired
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc;
  }
}

यह मुझे एक्सएमएल से निम्नलिखित पंक्तियों को हटाने की अनुमति देता है:

<property name="bbb" ref="bBean" />
<property name="ccc" ref="cBean" />

मेरा एक्सएमएल अब इसे सरल बना दिया गया है:

<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />

जब मैं संदर्भ लोड करता हूं तो मुझे निम्न आउटपुट मिलता है:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]

ठीक है, यह गलत है! क्या हुआ? मेरी संपत्तियों का स्वामित्व क्यों नहीं है?

खैर, एनोटेशन एक अच्छी सुविधा है लेकिन खुद से वे कुछ भी नहीं करते हैं। वे सिर्फ सामान एनोटेट करते हैं। एनोटेशन खोजने और उनके साथ कुछ करने के लिए आपको एक प्रसंस्करण टूल की आवश्यकता है।

<context:annotation-config> बचाव के लिए। यह एनोटेशन के लिए क्रियाओं को सक्रिय करता है जो इसे उसी अनुप्रयोग संदर्भ में परिभाषित बीन्स पर पाता है जहां स्वयं परिभाषित किया जाता है।

अगर मैं अपना एक्सएमएल इस में बदलता हूं:

<context:annotation-config />
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />

जब मैं एप्लिकेशन संदर्भ लोड करता हूं तो मुझे उचित परिणाम मिलता है:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

ठीक है, यह अच्छा है, लेकिन मैंने एक्सएमएल से दो पंक्तियां हटा दी हैं और एक जोड़ा है। यह एक बहुत बड़ा अंतर नहीं है। एनोटेशन के साथ विचार यह है कि यह एक्सएमएल को हटाना है।

तो आइए एक्सएमएल परिभाषाओं को हटा दें और उन सभी को एनोटेशन के साथ बदलें:

package com.xxx;
import org.springframework.stereotype.Component;
@Component
public class B {
  public B() {
    System.out.println("creating bean B: " + this);
  }
}

package com.xxx;
import org.springframework.stereotype.Component;
@Component
public class C {
  public C() {
    System.out.println("creating bean C: " + this);
  }
}

package com.yyy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.xxx.B;
import com.xxx.C;
@Component
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  @Autowired
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  @Autowired
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc;
  }
}

एक्सएमएल में रहते हुए हम केवल यह रखते हैं:

<context:annotation-config />

हम संदर्भ लोड करते हैं और परिणाम है ... कुछ भी नहीं। कोई सेम नहीं बनाया जाता है, कोई सेम स्वचालित नहीं होते हैं। कुछ भी तो नहीं!

ऐसा इसलिए है क्योंकि, जैसा कि मैंने पहले अनुच्छेद में कहा था, <context:annotation-config /> केवल एप्लिकेशन संदर्भ में पंजीकृत बीन्स पर काम करता है। क्योंकि मैंने तीन बीन्स के लिए एक्सएमएल कॉन्फ़िगरेशन हटा दिया है, वहां कोई बीन नहीं बनाया गया है और <context:annotation-config /> पर काम करने के लिए कोई "लक्ष्य" नहीं है।

लेकिन यह <context:component-scan> लिए कोई समस्या नहीं होगी जो काम करने के लिए "लक्ष्य" के लिए एक पैकेज स्कैन कर सकता है। आइए एक्सएमएल कॉन्फ़िगरेशन की सामग्री को निम्न प्रविष्टि में बदलें:

<context:component-scan base-package="com.xxx" />

जब मैं संदर्भ लोड करता हूं तो मुझे निम्न आउटपुट मिलता है:

creating bean B: [email protected]
creating bean C: [email protected]

हम्मम्म ... कुछ गुम है। क्यूं कर?

यदि आप कक्षाओं में com.yyy , तो कक्षा A में पैकेज com.yyy लेकिन मैंने पैकेज com.xxx का उपयोग करने के लिए <context:component-scan> com.xxx <context:component-scan> में निर्दिष्ट किया है, इसलिए यह पूरी तरह से मेरी कक्षा को चूक गया और केवल B और C उठाया गया com.xxx पैकेज पर हैं।

इसे ठीक करने के लिए, मैं यह अन्य पैकेज भी जोड़ता हूं:

<context:component-scan base-package="com.xxx,com.yyy" />

और अब हमें अपेक्षित परिणाम मिलते हैं:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

और बस! अब आपके पास एक्सएमएल परिभाषाएं नहीं हैं, आपके पास एनोटेशन हैं।

अंतिम उदाहरण के रूप में, एनओ B और C को एनोटेटेड कक्षाएं रखते हुए और एक्सएमएल में निम्नलिखित जोड़ना, संदर्भ लोड करने के बाद हमें क्या मिलेगा?

<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />

हमें अभी भी सही परिणाम मिल रहा है:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

भले ही कक्षा A लिए बीन स्कैनिंग द्वारा प्राप्त नहीं किया गया हो, फिर भी प्रोसेसिंग टूल को एप्लिकेशन संदर्भ में पंजीकृत सभी बीन्स पर <context:component-scan> द्वारा लागू किया जाता है, यहां तक ​​कि A लिए भी जो एक्सएमएल में मैन्युअल रूप से पंजीकृत था।

लेकिन क्या होगा यदि हमारे पास निम्न XML है, तो क्या हमें डुप्लिकेट बीन्स मिलेंगे क्योंकि हमने दोनों <context:annotation-config /> और <context:component-scan> दोनों निर्दिष्ट किए हैं?

<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />

नहीं, कोई डुप्लीकेट नहीं, हम फिर से अपेक्षित परिणाम प्राप्त करते हैं:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

ऐसा इसलिए है क्योंकि दोनों टैग एक ही प्रोसेसिंग टूल पंजीकृत करते हैं ( <context:annotation-config /> को छोड़ा जा सकता है यदि <context:component-scan> निर्दिष्ट है) लेकिन वसंत केवल उन्हें एक बार चलाने का ख्याल रखता है।

यहां तक ​​कि यदि आप प्रोसेसिंग टूल को कई बार पंजीकृत करते हैं, तो वसंत अभी भी सुनिश्चित करेगा कि वे केवल एक बार अपने जादू करते हैं; यह एक्सएमएल:

<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
<bean id="bla" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla1" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla2" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla3" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />

अभी भी निम्नलिखित परिणाम उत्पन्न करेगा:

creating bean B: [email protected]
creating bean C: [email protected]
creating bean A: [email protected]
setting A.bbb with [email protected]
setting A.ccc with [email protected]

ठीक है, यह रैप के बारे में है।

मुझे आशा है कि @Tomasz Nurkiewicz और @ सेन पैट्रिक फ़्लॉइड के जवाबों के साथ यह जानकारी आपको समझने की आवश्यकता है कि <context:annotation-config> और <context:component-scan> घटक- <context:component-scan> कार्य कैसे करें।


<context:annotation-config> टैग वसंत को @Autowired एनोटेशन युक्त कक्षाओं की निर्भरता आवश्यकताओं को स्वचालित रूप से हल करने के लिए कोडबेस को स्कैन करने के लिए कहता है।

स्प्रिंग 2.5 जेएसआर -250 एनोटेशन जैसे कि @ रिसोर्स, @ पोस्टकस्ट्रक्चर, और @ प्रीडेस्ट्राय के लिए भी समर्थन जोड़ता है। इन एनोटेशन के उपयोग के लिए भी कुछ बीनपोस्ट प्रोसेसर स्प्रिंग कंटेनर के भीतर पंजीकृत होना आवश्यक है। हमेशा की तरह, इन्हें व्यक्तिगत बीन परिभाषाओं के रूप में पंजीकृत किया जा सकता है, लेकिन वसंत विन्यास में <context:annotation-config> टैग सहित उन्हें भी निहित रूप से पंजीकृत किया जा सकता है।

एनोटेशन आधारित कॉन्फ़िगरेशन के वसंत दस्तावेज़ीकरण से लिया गया

वसंत स्वचालित रूप से 'स्टीरियोटाइप' कक्षाओं का पता लगाने और अनुप्रयोगकॉन्टेक्स्ट के साथ इसी बीनडिफिनिशन को पंजीकृत करने की क्षमता प्रदान करता है।

Org.springframework.stereotype के javadoc के अनुसार:

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

इस तरह के 'स्टीरियोटाइप' वर्गों को स्वत: पहचानने के लिए, <context:component-scan> टैग आवश्यक है।

<context:component-scan> टैग स्प्रिंग को पैकेज (और उसके सभी उप-पैकेज) के तहत इंजेक्शन योग्य बीन्स के लिए कोड स्कैन करने के लिए भी बताता है।


<context:component-scan base-package="package name" /> :

इसका उपयोग कंटेनर को बताने के लिए किया जाता है कि मेरे पैकेज में बीन कक्षाएं उन बीन कक्षाओं को स्कैन करती हैं। बीन के शीर्ष पर कंटेनर द्वारा बीन कक्षाओं को स्कैन करने के लिए हमें निम्नलिखित में से एक स्टीरियो प्रकार एनोटेशन लिखना होगा।

@Component , @Service , @Repository @Service , @Repository

<context:annotation-config /> :

अगर हम एक्सएमएल में स्पष्ट रूप से बीन टैग लिखना नहीं चाहते हैं तो कंटेनर जानता है कि बीन में ऑटो वायरिंग है या नहीं। @Autowired एनोटेशन का उपयोग करके यह संभव है। हमें कंटेनर को सूचित करना होगा कि context:annotation-config में मेरे बीन में ऑटो वायरिंग है context:annotation-config


<context:annotation-config>

केवल @Autowired और @Qualifer एनोटेशन को हल करता है, यह सब निर्भरता इंजेक्शन के बारे में है, अन्य एनोटेशन भी हैं जो एक ही काम करते हैं, मुझे लगता है कि कैसे @ इंजेक्ट, लेकिन सभी एनोटेशन के माध्यम से डी को हल करने के बारे में हैं।

सावधान रहें, भले ही आपने <context:annotation-config> तत्व घोषित किया हो , आपको अपनी कक्षा को एक बीन कैसे घोषित करना होगा , याद रखें कि हमारे पास तीन उपलब्ध विकल्प हैं

  • एक्सएमएल: <bean>
  • @ टिप्पणियां: @ कॉम्पोनेंट, @ सेवा, @ रिपोजिटरी, @ नियंत्रक
  • जावाकॉन्फिग: @ बीन

अब उसके पास

<context:component-scan>

यह दो चीजें करता है:

  • यह @Component, @Service, @Repository, @Controller और @ कॉन्फ़िगरेशन के साथ एनोटेटेड सभी कक्षाओं को स्कैन करता है और एक बीन बनाता है
  • यह वही काम करता है कि <context:annotation-config> करता है।

इसलिए यदि आप <context:component-scan> घोषित करते हैं, तो अब आवश्यक नहीं है <context:annotation-config> भी।

बस इतना ही

उदाहरण के लिए, एक आम परिदृश्य उदाहरण के लिए एक्सएमएल के माध्यम से केवल एक बीन घोषित करता है और डीओ को एनोटेशन के माध्यम से हल करता है

<bean id="serviceBeanA" class="com.something.CarServiceImpl" />
<bean id="serviceBeanB" class="com.something.PersonServiceImpl" />
<bean id="repositoryBeanA" class="com.something.CarRepository" />
<bean id="repositoryBeanB" class="com.something.PersonRepository" />

हमने केवल बीन्स घोषित किए हैं, <constructor-arg> और <property> बारे में कुछ नहीं, DI को @Autowired के माध्यम से अपने स्वयं के वर्गों में कॉन्फ़िगर किया गया है। इसका मतलब है कि सेवाओं का उपयोग उनके रिपोजिटरी घटकों के लिए @Autowired और रेपॉजिटरीज़ @ JutbcTemplate, DataSource आदि.com के लिए @Autowired का उपयोग करता है


<context:component-scan /> implicitly enables <context:annotation-config/>

<context:component-scan base-package="..." annotation-config="false"/> , अपनी कॉन्फ़िगरेशन @ सेवा, @ रिपोजिटरी , @ कॉम्पोनेंट में ठीक काम करता है, लेकिन @ ऑटोवायर , @ संसाधन और @ इंजेक्ट के साथ प्रयास करें काम नहीं करता

इसका मतलब है AutowiredAnnotationBeanPostProcessor सक्षम नहीं होगा और स्प्रिंग कंटेनर ऑटोवॉयरिंग एनोटेशन को संसाधित नहीं करेगा।







spring-3