2013-08-06 6 views
5

में डायनामिक रूप से सेवा कार्यान्वयन का चयन करें मैं वसंत 3.2 का उपयोग कर रहा हूं और एक शर्त के आधार पर गतिशील रूप से मेरे नियंत्रक में सेवा कार्यान्वयन चुनना चाहता हूं।स्प्रिंग

public interface DevService { 
    public void add(Device device); 
} 

public class DevServiceImpl implements DevService { 
    public void add(Device device) { 
    } 
} 

public class RemoteDevServiceImpl implements DevService { 
    public void add(Device device) { 
    } 
} 
मेरी नियंत्रक में

तो, पर कि क्या कार्रवाई स्थानीय साइट या दूरस्थ साइट पर निष्पादित किया जाना है निर्भर करता है, मैं या तो इसे स्थानीय स्तर पर निष्पादित करते समय या भेजने की जरूरत है: इस प्रकार मैं एक अंतरफलक और दो कार्यान्वयन है पर विचार करें इसे निष्पादित करने के लिए दूरस्थ साइट पर आदेश। अनिवार्य रूप से वह साइट जिस पर उपयोगकर्ता क्लिक करता है यह निर्धारित करता है कि कौन सी सेवा कॉल करने के लिए प्रयुक्त होती है। क्या कोई इसे हासिल करने के लिए एक साफ तरीका सुझा सकता है?

उत्तर

8

मान लीजिए कि आपको उत्पादन पर्यावरण में दोनों कार्यान्वयन की आवश्यकता है (यदि नहीं - वातावरण के बीच स्पष्ट रूप से विभाजित बीन्स के लिए स्प्रिंग प्रोफाइल का उपयोग करें)। सरल दृष्टिकोण होगा:

interface DevService 
{ 
    void add(Device d); 
    String getName(); 
} 

@Service("devServiceLocal") 
class DevServiceLocalImpl implements DevService 
{ 
    void add(Device d) {...} 
    String getName() {return "local";} 
} 

class Controller 
{ 
    @Autowired 
    Collection<DevService> services; 

    void doSomethingWithService() 
    { 
     // TODO: Check type somehow 
     String servType = "local"; 
     for(DevService s: services) 
     { 
     if(servType.equals(s.getName()) 
     { 
      // Call service methods 
      break; 
     } 
     } 
    } 
} 
0

आप @Named एनोटेशन का उपयोग कर सकते हैं, और नाम से बीन प्राप्त कर सकते हैं।

इस तरह, आप आधार नाम "सेवा नाम" को परिभाषित कर सकते हैं और आपके द्वारा समझाई गई शर्त के आधार पर "रिमोट" या "लोकल" जैसी कुछ प्रत्यय जोड़ सकते हैं। तुम भी आप (DevService)BeanFactory.getBean("beanName") उपयोग कर सकते हैं अपने गतिशील रूप से उत्पन्न नाम से इसे पाने के लिए, की तरह

@Named("ServiceNameRemote") और @Named("ServiceNameLocal") क्रमशः

अंत में अपने नियंत्रक पर

अपने सेम (सेवा कार्यान्वयन) टिप्पणी करने की आवश्यकता होगी।

0

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

package <PACKAGE NAME>; 

import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.ModelAttribute; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 

@Controller 
@RequestMapping("/device") 
public class DeviceController { 

    @RequestMapping(headers={"Host=*.local.domain.com"}) 
    public void localDevice(
     @ModelAttribute("device") Device device 
    ) { 
     ... 
    } 

    @RequestMapping(headers={"Host!=*.local.domain.com"}) 
    public void remoteDevice(
     @ModelAttribute("device") Device device 
    ) { 
     ... 
    } 

} 

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

2

आपका प्रश्न यह दर्शाता है कि "गतिशील रूप से" आप का मतलब है कि आप स्टार्टअप समय पर चयन करने में सक्षम होना चाहते हैं, लेकिन आपको इसे मध्यरात्रि में बदलने में सक्षम होने की आवश्यकता नहीं है। यदि ऐसा है, तो मैं @Profile का उपयोग करने की दृढ़ता से अनुशंसा करता हूं। एनोटेशन-आधारित कॉन्फ़िगरेशन का उपयोग करके मेरा सामान्य अभ्यास, प्रत्येक प्रोफ़ाइल के लिए एक अलग @Configuration कक्षा है जो प्रोफ़ाइल-विशिष्ट @Bean एस को परिभाषित करने की आवश्यकता है जो वहां उपलब्ध होने की आवश्यकता है। विकास-केवल @Controller एस को परिभाषित करना भी आसान है जो उत्पादन मोड में पूरी तरह से अक्षम हैं। टाइपो से बचने के लिए प्रत्येक प्रोफ़ाइल के लिए String स्थिरांक वाले वर्ग को परिभाषित करें।