2010-03-29 9 views
12

क्या रूबी में method_missing तकनीक की तरह संदेश (विधि कॉल) को अवरुद्ध करने के लिए जावा में कोई तकनीक उपलब्ध है? यह सज्जाकार और प्रॉक्सी कोडिंग बहुत आसानी से, रूबी में की तरह की अनुमति होगी:सजावट के लिए जावा विधि गायब (अला रूबी)?

:Client   p:Proxy     im:Implementation 
-------   ----------     ----------------- 

p.foo() -------> method_missing() 
        do_something 
        im.foo() ------------------> do_foo 


p.bar() --------> method_missing() 
        do_something_more 
        im.bar() -------------------> do_bar 

(नोट: प्रॉक्सी केवल एक विधि है: method_missing())

उत्तर

17

जैसा कि अन्य ने पहले से ही सही कहा है, एक डायनामिक प्रॉक्सी का उपयोग करें। यहां एक उदाहरण दिया गया है।

यह कक्षा "हैमर लिस्टर" इंटरफ़ेस में घोषित विधियों के आमंत्रण को रोकने के लिए डायनामिक प्रॉक्सी का उपयोग करती है। यह कुछ लॉगिंग करता है और फिर "असली" हैमर लिस्टनर कार्यान्वयन के लिए प्रतिनिधि करता है (हां, वही बात एओपी के साथ की जा सकती है)।

प्रॉक्सी इंस्टेंटेशन के लिए नई इंस्टेंस विधि देखें (ध्यान दें कि आपको प्रॉक्सी को कार्यान्वित करने वाले इंटरफ़ेस में पारित करने की आवश्यकता है - एक प्रॉक्सी एकाधिक इंटरफ़ेस को कार्यान्वित कर सकता है)।

प्रॉक्सी उपकरण पर इंटरफेस पर सभी विधि आमंत्रण "InvokeHandler" इंटरफ़ेस में घोषित "invoke" विधि को कॉल के रूप में समाप्त हो जाएगा। सभी प्रॉक्सी हैंडलर को इस इंटरफेस को लागू करना होगा।

import java.lang.reflect.*; 

/** 
* Decorates a HammerListener instance, adding BEFORE/AFTER 
* log messages around all methods exposed in the HammerListener interface. 
*/ 

public class HammerListenerDecorator implements InvocationHandler { 

    private final HammerListener delegate; 

    static HammerListener newInstance(HammerListener delegate) { 
     ClassLoader cl = Thread.currentThread().getContextClassLoader(); 
     return (HammerListener)Proxy.newProxyInstance(cl, new Class[]{HammerListener.class}, 
      new HammerListenerDecorator(delegate)); 
    } 

    private HammerListenerDecorator(HammerListener delegate) { 
     this.delegate = delegate; 
    } 

    @Override 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
     logger.info("BEFORE " + method.getName() + " {{{" + argsToString(args) + "}}}"); 
     Object rtn = method.invoke(delegate, args); 
     logger.info("AFTER " + method.getName()); 
     return rtn; 
    } 

    private String argsToString(Object[] args) { 
     StringBuilder sb = new StringBuilder(); 
     for (Object o : args) { 
      sb.append(String.valueOf(o)).append(" "); 
     } 
     return sb.toString(); 
    } 
} 
+0

@ killdash10: धन्यवाद, बहुत उपयोगी! – cibercitizen1

+0

यह थोड़ी देर में मैंने देखा है सबसे आश्चर्यजनक बात है। –

+0

"प्रॉक्सी लागू करने वाले इंटरफेस पर सभी विधि आमंत्रण" - तो, ​​यदि आप किसी भी संभावित * विधि आमंत्रण को अवरुद्ध करना चाहते हैं तो उपयोगी नहीं है? – allquixotic

0

नहीं वास्तव में। निकटतम समकक्ष Dynamic Proxy ऑब्जेक्ट है, लेकिन इसमें कुछ सीमाएं हैं (यानी, इसे केवल प्रतिबिंब के माध्यम से ही बुलाया जा सकता है)।

+0

आपको यह विचार क्या मिला? प्रॉक्सी ऑब्जेक्ट को किसी अन्य ऑब्जेक्ट की तरह डाला जा सकता है और लगाया जा सकता है। – skaffman

2

java.lang.reflect.Proxy और java.lang.reflect.InvocationHandler या Aspect- उन्मुख प्रोग्रामिंग सामान्य रूप से (उदाहरण के लिए AspectJ) देखें।

4

java.lang.reflect.Proxy रनटाइम पर निर्दिष्ट इंटरफेस के लिए रनटाइम प्रॉक्सी उत्पन्न करने के लिए प्रारंभिक बिंदु है। यह आपको प्रॉक्सी करने के लिए इंटरफ़ेस निर्दिष्ट करने की अनुमति देता है, साथ ही साथ "वास्तविक" आमंत्रण को संभालने वाली ऑब्जेक्ट को, जो आप चुनते हैं, निश्चित रूप से बस कुछ और कह सकते हैं।

Proxy कक्षा का आउटपुट एक ऐसा ऑब्जेक्ट है जिसे आप अपने वांछित इंटरफ़ेस प्रकार में डाल सकते हैं, और किसी भी अन्य ऑब्जेक्ट की तरह उपयोग और इनकार कर सकते हैं।

यह रूबी जैसी गतिशील भाषा के साथ जितना आसान नहीं होगा, लेकिन आप जावा जैसी दृढ़ स्थिर भाषा के लिए कीमत चुकाते हैं।

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