2012-05-03 28 views
15

Dependency injection, delayed injection praxis से एक निरंतरता। मैं मुख्य वर्ग है:वसंत गतिशील इंजेक्शन, कारखाने की तरह पैटर्न

package test; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext; 
import org.springframework.stereotype.Component; 

import java.util.List; 
import java.util.Scanner; 

@Component 
public class Main { 
    @Autowired 
    private StringValidator stringValidator; 

    @Autowired 
    private StringService stringService; 

    @Autowired 
    private ValidationService validationService; 

    public void main() { 
     scanKeyboardCreateLists(); 

     stringValidator.validate(); 

     final List<String> validatedList = stringValidator.getValidatedList(); 
     for (String currentValid : validatedList) { 
      System.out.println(currentValid); 
     } 
    } 

    private void scanKeyboardCreateLists() { 
     //Let's presume the user interacts with the GUI, dynamically changing the object graph... 
     //Needless to say, this is past container initialization... 
     Scanner scanner = new Scanner(System.in); 
     int choice = scanner.nextInt(); 

     //Delayed creation, dynamic 
     if (choice == 0) { 
      stringService.createList(); 
      validationService.createList(); 
     } else { 
      stringService.createSecondList(); 
      validationService.createSecondList(); 
     } 
    } 

    public static void main(String[] args) { 
     ApplicationContext container = new ClassPathXmlApplicationContext("/META-INF/spring/applicationContext.xml"); 
     container.getBean(Main.class).main(); 
    } 
} 

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

कोड के बाकी यहाँ है:

package test; 

import java.util.List; 

public interface Stringable { 
    List<String> getStringList(); 
} 

package test; 

import org.springframework.stereotype.Component; 

import java.util.ArrayList; 

@Component 
public class StringList extends ArrayList<String> { 
} 

package test; 

import org.springframework.stereotype.Component; 

import javax.inject.Inject; 
import java.util.ArrayList; 
import java.util.List; 

@Component 
public class StringService implements Stringable { 

    private List<String> stringList; 

    @Inject 
    public StringService(final ArrayList<String> stringList) { 
     this.stringList = stringList; 
    } 

    //Simplified 
    public void createList() { 
     stringList.add("FILE1.txt"); 
     stringList.add("FILE1.dat"); 
     stringList.add("FILE1.pdf"); 
     stringList.add("FILE1.rdf"); 
    } 

    public void createSecondList() { 
     stringList.add("FILE2.txt"); 
     stringList.add("FILE2.dat"); 
     stringList.add("FILE3.pdf"); 
     stringList.add("FILE3.rdf"); 
    } 

    @Override 
    public List<String> getStringList() { 
     return stringList; 
    } 
} 

package test; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Component; 

import java.util.ArrayList; 
import java.util.List; 

@Component 
public class StringValidator { 
    private List<String> stringList; 
    private List<String> validationList; 

    private final List<String> validatedList = new ArrayList<String>(); 

    @Autowired 
    public StringValidator(final ArrayList<String> stringList, 
          final ArrayList<String> validationList) { 
     this.stringList = stringList; 
     this.validationList = validationList; 
    } 

    public void validate() { 
     for (String currentString : stringList) { 
      for (String currentValidation : validationList) { 
       if (currentString.equalsIgnoreCase(currentValidation)) { 
        validatedList.add(currentString); 
       } 
      } 
     } 
    } 

    public List<String> getValidatedList() { 
     return validatedList; 
    } 
} 

package test; 

import java.util.List; 

public interface Validateable { 
    List<String> getValidationList(); 
} 

package test; 

import org.springframework.stereotype.Component; 

import java.util.ArrayList; 

@Component 
public class ValidationList extends ArrayList<String> { 
} 

package test; 

import org.springframework.stereotype.Component; 

import javax.inject.Inject; 
import java.util.ArrayList; 
import java.util.List; 

@Component 
public class ValidationService implements Validateable { 

    private List<String> validationList; 

    @Inject 
    public ValidationService(final ArrayList<String> validationList) { 
     this.validationList = validationList; 
    } 

    //Simplified... 
    public void createList() { 
     validationList.add("FILE1.txt"); 
     validationList.add("FILE2.txt"); 
     validationList.add("FILE3.txt"); 
     validationList.add("FILE4.txt"); 
    } 

    public void createSecondList() { 
     validationList.add("FILE5.txt"); 
     validationList.add("FILE6.txt"); 
     validationList.add("FILE7.txt"); 
     validationList.add("FILE8.txt"); 
    } 

    @Override 
    public List<String> getValidationList() { 
     return validationList; 
    } 
} 

किसी को भी पता है कि कैसे मैं विधि कॉल createList() या createSecondList() का समाधान होगा - निर्माता जो काफी बलों डिजाइन का उपयोग किए बिना। मैं एक कारखाने के बारे में सोच रहा था, लेकिन एक बड़ी परिमाण की परियोजना में प्रत्येक वर्ग के लिए एक कारखाना एक अच्छा विचार प्रतीत नहीं होता है।

कुछ की तरह:

<bean ... factory-method="..." depends-on="..." lazy-init="..."/> 

और कारखाने विधि में वर्ग का दृष्टांत और विधि createList फोन()। या इसे इस तरह से कॉल करें, कुछ विधि से - जो फिर से खराब दिखता है, ऑब्जेक्ट ग्राफ़ को तुरंत चालू करने की ज़िम्मेदारी रखने के लिए विधि को मजबूर करता है।

क्रम निर्भरता है कि मैं क्रम में हल करना चाहते हैं की तस्वीर bellow है:

enter image description here

वहाँ किसी और तरीके से मैं कंटेनर इस्तेमाल कर सकते हैं उपयोगकर्ता बातचीत के आधार पर गतिशील आलसी initalization हासिल करने के लिए है ?

धन्यवाद।

+1

मुझे नहीं पता कि आप क्या पूछ रहे हैं। "_solve_ विधि कॉल createList() या createSecondList()" से आपका क्या मतलब है? यदि मैं अपने अनुमान में सही हूं कि आप क्या करने की कोशिश कर रहे हैं (और मुझे शक है), तो मैं एक फैक्ट्री क्लास तैयार करूंगा जिसमें एक (स्थैतिक?) फैक्ट्री विधि होगी जो इंटरैक्टिव तर्क लेती है और उपयुक्त सूची बनाती है, फिर इंजेक्ट करें उस मुख्य श्रेणी में उस वर्ग का कारखाना वस्तु। –

+0

मैंने सोचा कि आप संदर्भ से समझेंगे। एक महान सवाल लेखक नहीं है। हाँ, ऐसा कुछ। सवाल बोल्ड किया गया है। कारखाने के अलावा (स्थिर, निश्चित रूप से) और वस्तुओं के पुल/प्रारंभिकरण (मुख्य वर्ग में प्रारंभिकता के साथ, "मुख्य" विधि) का उपयोग करके, मैं गतिशील ऑब्जेक्ट ग्राफ़ कैसे बना सकता हूं इसलिए मुझे आर्किटेक्चर के बारे में चिंता करने की ज़रूरत नहीं है "कोड "मेरे आवेदन में। आप अपने मुख्य वस्तु में फैक्ट्री ऑब्जेक्ट को इंजेक्ट क्यों करेंगे? यदि आपके सभी वर्ग गतिशील हैं तो आपके पास बहुत काम होगा। चूंकि आपके पास प्रत्येक गतिशील वर्ग पर एक कारखाना होना चाहिए। मुझे अभी भी विश्वास है कि एक आसान समाधान है :) – pfh

उत्तर

10

यदि आप चाहते हैं कि आपकी कक्षा के कुछ सदस्य को गतिशील रूप से प्रारंभिक गेटटर को प्रत्येक कॉल पर पॉप्युलेट किया जाए, तो आप लुकअप विधि इंजेक्शन को आजमा सकते हैं। पीपी 3.3.4.1here पढ़ें।

तो भले ही गतिशील सदस्य वाले वर्ग को scope=singletone (वसंत बीन कंटेनर के लिए डिफ़ॉल्ट) में बनाया गया हो, हर बार जब आप एक लुकअप विधि निर्दिष्ट फ़ील्ड को प्राप्त करेंगे, तो आपको व्यवसाय तर्क के अनुसार उचित वस्तु मिल जाएगी लुकअप विधि के अंदर लागू किया गया। आपके मामले में सूची एक इंटरफ़ेस है ताकि आप आसानी से अपनी लुकअप विधि के अंदर सत्यापन को कार्यान्वित कर सकें और एक मान्य सूची वापस कर सकें।

संपादित करें:

मैं वसंत दस्तावेज में बेहतर example मिला - मुझे लगता है कि यह बहुत स्पष्ट है। जब आप Main वर्ग अपनी List सदस्य के लिए एक देखने विधि आवंटित कॉन्फ़िगर "3.4.6.1 लुक विधि इंजेक्शन"

पर एक नजर डालें - यह कहा जाएगा जब भी आप List सेम का एक नया उदाहरण की जरूरत है।

शुभकामनाएं!

+0

यह एक अच्छा विचार है, लेकिन फैक्ट्री को एक विधि में ले जाना Arhictecture कोड को हल करने के लिए प्रतीत नहीं होता है। इसके अलावा, यह जटिलता जोड़ता है। अचानक, विधि आवश्यक प्रकार वापस करनी होगी। और फिर मेरे पास एन तरीके हैं जब मुझे एन प्रकार की आवश्यकता होती है। क्या मैं यह गलत देख रहा हूँ? वसंत में @AssistedInject (http://code.google.com/p/google-guice/wiki/AssistedInject, https://jira.springsource.org/browse/SPR-5192) जैसी कोई चीज़ नहीं है? यदि आपके पास "गतिशील" एप्लिकेशन है तो क्या आप आमतौर पर ऐसा कुछ करते हैं? ऐसा लगता है कि प्रोग्रामर अनुभवी प्रोग्रामर अक्सर उस यात्रा पर नहीं जाते हैं ... – pfh

+0

मुझे लगता है कि एक लुकअप विधि पर्याप्त है (सुनिश्चित करें कि आपने इस बिंदु को याद नहीं किया है) :) लुकअप विधि एक ऑब्जेक्ट लौटाएगी जो कुछ आम लागू करती है इंटरफ़ेस (सूची?) या यहां तक ​​कि एक मार्कर इंटरफ़ेस भी। लुकअप विधि का सटीक प्रकार का ऑब्जेक्ट का निर्णय कुछ बाहरी स्रोत (कॉन्फ़िगरेशन फ़ाइल, उपयोगकर्ता इनपुट इत्यादि) पर आधारित हो सकता है लेकिन सभी संभावित प्रकारों को अग्रिम में – aviad

+0

में जाना जाने की आवश्यकता है, लेकिन मैं बिंदु को याद करने की कोशिश नहीं कर रहा हूं, लेकिन ऐसा लगता है कि मैं असफल रहा हूँ। मुझे गलत मत समझो, मैं जवाब के लिए आभारी हूं। यह - http://java.dzone.com/articles/pragmatic-look-method जो मैं प्राप्त करना चाहता हूं उससे बहुत अलग है। मैं उन सभी कोणों से इसे देखने की कोशिश कर रहा हूं जिनके बारे में मैं सोच सकता हूं ... आप वास्तव में एक उदाहरण बनाने और इसे प्रदर्शित करने का प्रयास कैसे करते हैं? हां, मैं मार्कर इंटरफ़ेस का उपयोग कर सकता हूं।लेकिन फिर मैं "बस" रनटाइम निर्भरता को हल करना है। और "विधि इंजेक्शन" वास्तव में इसे हल नहीं करता है। रनटाइम के आधार पर मैं विभिन्न ऑब्जेक्ट्स को कैसे चालू कर सकता हूं? मैंने अपना प्रश्न अपडेट किया ताकि आप एक और नज़र देख सकें। – pfh

2

उपयोगकर्ता की तरह लगता है 1 ..ऑब्जेक्ट्स के एन ग्राफ और आप केवल वह लोड करना चाहते हैं जिसे उपयोगकर्ता रनटाइम पर चुनता है। यदि ग्राफ डिज़ाइन समय पर ज्ञात हैं लेकिन उपयोगकर्ता सिर्फ वही चुनता है जिसे वे चाहते हैं तो यह मुझे लगता है कि आपके पास एप्लिकेशन कॉन्टैक्स का एक गुच्छा है और आप केवल एक एप्लिकेशन कॉन्टेक्स्ट लोड करना चाहते हैं जिसे उपयोगकर्ता रनटाइम पर चुनता है। तो क्यों न केवल ApplicationContexts के सेट को परिभाषित करें और फिर रनटाइम पर दाएं को तुरंत चालू करें। चूंकि स्प्रिंग जावा कॉन्फ़िगर का समर्थन करता है, इसलिए इन कॉन्फ़िगरेशन को जावा कक्षाओं के रूप में परिभाषित करने के लिए समझदारी हो सकती है ताकि आप विरासत प्राप्त कर सकें और किसी भी कोड को काटने/पेस्ट करने से बच सकें।

+0

सही। लेकिन समस्या यह है कि कंटेनर "पता नहीं" रनटाइम पर ऑब्जेक्ट्स क्या हैं। यदि आपके पास फ़ाइल है, और उपयोगकर्ता को इसे चुनने की उम्मीद है, तो आप वास्तव में सभी संभावित संयोजनों को स्थाई रूप से पूर्वनिर्धारित नहीं कर सकते हैं। विचार अच्छा है, लेकिन गतिशील भाग हल हो गया है (सूची को "वैश्विक" बीन के रूप में उपयोग करना)। वास्तविक समस्या यह है कि ऑब्जेक्ट को तुरंत चालू करने के लिए जब उपयोगकर्ता कार्य करता है (उदा। बटन पर क्लिक करें), यह जानकर कि आपकी विधि में आपका प्रारंभिकरण है। मुझे किसी प्रकार का आलसी इनटाइलाइजेशन चाहिए, लेकिन मेरी मुख्य विधि में कारखानों या इनटाइलाइजेशन विधियों के साथ कोड सफाई को त्यागना नहीं चाहते हैं। – pfh

3

वसंत को फिर से उपयोग करने योग्य घटक इंजेक्शन के लिए डिज़ाइन किया गया है, न कि व्यापार डेटा हेरफेर और इंजेक्शन के लिए।

वास्तव में निर्भरता इंजेक्शन में कुछ डेटा का उपयोग किया जाता है, लेकिन केवल घटक डेटा कॉन्फ़िगर करने के लिए घटकों के व्यवहार को कॉन्फ़िगर करने के लिए।

वैसे, निम्नलिखित विकल्प आपके मामले में इस्तेमाल किया जा सकता है: धन्यवाद BeanFactoryAware interface के साथ एक BeanFactory और गुंजाइश = "प्रोटोटाइप" का उपयोग करते हैं, आप that example में या that other question: creating bean on demand से की तरह getBean() लागू द्वारा एक सेम उत्पन्न कर सकते हैं।

अगर आप सेम तैयार करने के लिए की एक सीमित संख्या है एक वैकल्पिक विकल्प सामान्य सेम निर्माण का उपयोग करने के the same way lacking beans are mocked

अब विचार है कि वसंत कभी नहीं कचरा इसके संदर्भ में सेम एकत्र करता है। तो स्प्रिंग बीन्स को व्यापार डेटा रखने के लिए मेमोरी खपत के लिए जोखिम भरा है।

यदि आपका लक्ष्य अलग है (मुझे उम्मीद है), हो सकता है कि आप अपने बहु-किरायेदार समर्थन द्वारा कार्यान्वित करने की कोशिश कर रहे हैं। वसंत किरायेदारी प्रदान करता है यदि आपके पास विशिष्ट घटकों या व्यवहार के साथ लागू करने के लिए अलग-अलग व्यावसायिक संदर्भ हैं।

+0

नहीं, मैंने, एक बार फिर, buisness डेटा और वास्तुकला को गठबंधन करने की कोशिश की। समस्या यह है कि, यदि आप ओओपी आर्किटेक्चर का उपयोग कर रहे हैं, तो आप वास्तव में इंजेक्शन के लिए कंटेनर का उपयोग नहीं कर सकते हैं। यदि आप स्टेटलेस सेवाओं का उपयोग शुरू करते हैं और डेटा ऑब्जेक्ट्स और सेवाओं में कोड विभाजित करते हैं, तो आप वसंत के बहुत सारे उपयोग कर सकते हैं। लेकिन मैं इसके लिए नहीं हूँ। मुझे लगता है कि राज्यव्यापी वस्तुएं अभी भी शासन करती हैं (यह मेरा विचार है)। मैं कचरा संग्रह समझता हूं, वस्तु एक सिंगलटन है, कोई समस्या नहीं होगी। मामूली स्मृति वृद्धि लगभग अदृश्य है। समस्या अभी भी बनी हुई है - आप कोड को विबाइबिल अरिटेक्चर कोड में "कट" नहीं कर सकते हैं। – pfh

+0

एम्बेडेड व्यापार डेटा के साथ राज्य के घटक के लिए ठीक है। लेकिन अगर यह सिर्फ एक सिंगलटन है तो समवर्ती या बहु-उपयोगकर्ता पहुंच को कैसे संभालें। क्या आप सिंगलटन के अंदर थ्रेड-स्थानीय चर का उपयोग करेंगे? क्या आप फैक्ट्री पैटर्न पर स्विच करेंगे? ईमानदारी से जावाईई अवधारणाओं को थ्रेड-सुरक्षित और स्केलेबल होने के लिए पैटर्न के चारों ओर डिजाइन किया गया है। वसंत को एक ही पैटर्न को हल्के तरीके से उपयोग करने के लिए डिज़ाइन किया गया है लेकिन उद्देश्य बनी हुई है: प्रदर्शन के लिए समरूपता। –

+0

"इसे काम करें, फिर अनुकूलित करें"। लक्ष्य अभी समेकन से निपटने के लिए नहीं है, विचार एक गतिशील वातावरण में एक कंटेनर का उपयोग करने के लिए एक तरीका के साथ आना था।किसी भी प्रकार के कंटेनर का उपयोग करते समय राज्यव्यापी कक्षाओं से निपटना अभी भी एक समस्या है। इसे एक तरफ रखते हुए, इसके साथ निपटने के लिए आपके विचार बहुत अच्छे हैं। और उद्देश्य "प्रदर्शन के लिए सहमति" वास्तव में एक नई बात नहीं है। तो, हाँ, आप प्रति उपयोगकर्ता एक सिंगलटन का उपयोग करके इसे काम कर सकते हैं (आप तर्क दे सकते हैं कि यह सिंगलटन नहीं होगा)। लेकिन वास्तव में एक महान कंटेनर तक पहुंचने के लिए इसे गतिशील बनाना होगा। – pfh