2008-12-13 37 views
10

के लिए एक सामान्य "बैकएंड" लाइब्रेरी है, मैं वर्तमान में जावा में लागू एक विशेष, व्याख्या, प्रोग्रामिंग भाषा के साथ काम कर रहा हूं। भाषा के बहुत छोटे हिस्से के रूप में, मैं जावा में कॉल करने की क्षमता जोड़ना चाहता हूं। प्रतिबिंब के सभी नट-किरकिरा में कूदने से पहले, मैं सोच रहा था कि क्या किसी को जावा कोड को प्रतिबिंबित करने के "बैकएंड" हिस्से को करने के लिए सामान्य पुस्तकालय के बारे में पता था।क्या जावा प्रतिबिंब

यही है, मैं एक जावा स्ट्रिंग (या कन्स्ट्रक्टर, या फील्ड एक्सेस) का प्रतिनिधित्व करने वाली कुछ डेटा संरचना में एक स्ट्रिंग (मैं व्याकरण परिभाषित करता हूं) का विश्लेषण करता हूं और फिर उस पुस्तकालय में उस डेटा संरचना को पास करता हूं जो कॉल और रिटर्न को आमंत्रित करता है परिणाम। विशेष रूप से, मैं चाहता हूँ यह पहले से ही सब किनारे मामलों है कि मैं यह पता लगाने की नहीं करना चाहते को संभालने के लिए: स्वतः सही विधि (एक बुद्धिमान Class.getDeclaredMethod तरह तर्कों के प्रकार के आधार पर लेने

  • ())
  • सरणियों और सामान्य वस्तु के बीच हैंडल भेद का संदर्भ
  • आदि

मैं एक छोटे से समय बिताया है JVM पर गतिशील भाषाओं के कार्यान्वयन को देखते हुए, लेकिन इन आम तौर पर ज्यादा मैं तुलना में अधिक जटिल हैं मैं कण के लिए देख रहा हूं, या अत्यधिक अनुकूलन कर रहा हूं ular भाषा।

एक और विकल्प है कि मेरे व्याकरण को कुछ गतिशील भाषा में एक स्ट्रिंग में परिवर्तित करना और राइनो या कुछ के साथ इसका आह्वान करना है, लेकिन यह मेरी तुलना में थोड़ा अधिक ओवरहेड है।

धन्यवाद!

उत्तर

6

बस अपने उत्तर पर एक टिप्पणी; वास्तव में beanutils पैरामीटर के एक सेट दिए गए "एक करीबी मैच" पाने के लिए समर्थन है। getMatchingAccessibleMethod()

बीनयूट्स वास्तव में शक्तिशाली है और कक्षाओं का निरीक्षण करने के लिए बहुत सारी उपयोगिता विधियां हैं। वही समर्थन रचनाकारों के लिए स्वाभाविक रूप से उपलब्ध है।

2

Java's scripting support पर एक नज़र डालें; मुझे विश्वास है कि यह आपकी समस्या से निपटने में आपकी मदद करेगा।

+0

नहीं। मैं ऑब्जेक्ट आवेक (ऑब्जेक्ट ऑब्जेक्ट, स्ट्रिंग नेमऑफमेथ, ऑब्जेक्ट [] args) जैसे किसी विधि के साथ कुछ ढूंढ रहा हूं "जो सही तरीका पाता है (विरासत लेना और खाते में रूपांतरण टाइप करना) और इसे कॉल करें। जावा स्क्रिप्टिंग बस मुझे मौजूदा स्क्रिप्टिंग भाषा में स्ट्रिंग का मूल्यांकन करने दें। –

+0

खैर, जावा स्क्रिप्टिंग जावा से स्क्रिप्टिंग भाषाओं को आमंत्रित करने से अधिक करती है, अगर मुझे गलत नहीं लगता है- यह जावा ऑब्जेक्ट्स (दस्तावेज़ों में बाध्यकारी के रूप में संदर्भित) के साथ स्क्रिप्टिंग कोड को इंटरैक्ट करने के लिए तंत्र प्रदान करता है, जो आपके जैसा ही दिखता है करने की कोशिश कर रहे हैं। – alex

+0

... कम से कम, मौजूदा स्क्रिप्टिंग कार्यान्वयन पर एक नज़र डालने से आपको – alex

7

पर एक नज़र FEST Reflection मॉड्यूल का प्रयास है। जावा प्रतिबिंब करने के लिए यह एक स्पष्ट तरीका है। उदाहरण के लिए:

String name = method("get").withReturnType(String.class) 
         .withParameterTypes(int.class) 
         .in(names) 
         .invoke(8); 
0

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

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

private ScriptEngine engine = ... initialize with JavaScript engine ... 

private Object invoke(Object object, String methodName, Object[] args) 
    throws RhsFunctionException 
{ 
    // build up "o.method(arg0, arg1, arg2, ...)" 
    StringBuilder exp = new StringBuilder("o." + methodName); 
    engine.put("o", object); 
    buildArgs(arguments, exp); 

    try { 
     return engine.eval(exp.toString()); 
    } 
    catch (ScriptException e) { 
     throw new RhsFunctionException(e.getMessage(), e); 
    } 
} 

private void buildArgs(Object[] args, StringBuilder exp) 
{ 
    // Use bindings to avoid having to escape arguments 
    exp.append('('); 
    int i = 0; 
    for(Symbol arg : args) { 
     String argName = "arg" + i; 
     engine.put(argName, arg); 
     if(i != 0) { 
      exp.append(','); 
     } 
     exp.append(argName); 
     ++i; 
    } 
    exp.append(')'); 
} 

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

कोई भी प्रतिक्रिया या वैकल्पिक समाधान स्वागत से अधिक हैं।

1

मैं दृढ़ता से स्प्रिंग्स ReflectionUtils वर्ग पर एक नज़र रखने पर भी विचार करता हूं। बहुत शक्तिशाली प्रतिबिंब हैंडलिंग।

1

मरे हुओं में से इस बढ़ाने के लिए:

invoke(Object object, String methodName, Object[] args) 

अपाचे कॉमन्स लैंग वास्तव में है कि विधि है। MethodUtils#invoke

0

मैंने इस धागे को पढ़ने के बाद इस कोड को लिखा और खोल दिया, शायद आप इसे उपयोगी पा सकते हैं।

https://github.com/yclian/Reflects.java/blob/master/src/test/java/my/jug/reflects/ReflectsTest.java

यह तो आप Predicate उपयोग कर सकते हैं तरीकों आप की तरह फिल्टर करने के लिए, अमरूद से प्रेरित है।

1

मैं एक पुस्तकालय com.lexicalscope.fluent प्रतिबिंब बनाने के लिए शुरू कर दिया है: धाराप्रवाह प्रतिबिंब जो hamcrest और lambdaj के साथ एकीकृत करता

आप इस तरह कोड लिख सकते हैं; जो एक कक्षा में सभी पद निर्माण एनोटेट तरीकों कॉल:

forEach(
    object(subject).methods(annotatedWith(PostConstruct.class)), 
    ReflectedMethod.class).call(); 

ब्लॉग पोस्ट यहाँ: http://www.lexicalscope.com/blog/category/software-projects/fluent-reflection/

प्रलेखन यहाँ: http://fluent-reflection.lexicalscope.com/

आप इसे Maven केंद्रीय यहां से प्राप्त कर सकते हैं: http://repo1.maven.org/maven2/com/lexicalscope/fluent-reflection/fluent-reflection/

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

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

+0

यह वास्तव में शक्तिशाली दिखता है। क्या आपके पास 1-2 और सरल उदाहरण भी हैं? –

+0

और सभी प्राप्त विधियों का चयन करने का उदाहरण: ऑब्जेक्ट (विषय)। विधि (कॉल करने योग्य हैसनाम स्टार्टिंग के साथ ("प्राप्त करें") और (कॉल करने योग्य हैसनोआरगमेंट्स()) और (नहीं (कॉल करने योग्य हैसवॉइडरेटर्न())); – lexicalscope

2

यदि आप सादगी की तलाश में हैं, तो मैंने जावा में प्रतिबिंब एपीआई तक पहुंच की सुविधा के लिए jOOR नामक एक साधारण लाइब्रेरी बनाई है। यह एक विशाल एपीआई के निर्माण के बिना सबसे आवश्यक कार्यों का समर्थन करता है। यहां एक उदाहरण दिया गया है कि जो कोड कोड कैसा दिखता है:

String world = 
on("java.lang.String") // Like Class.forName() 
.create("Hello World") // Call the most specific matching constructor 
.call("substring", 6) // Call the most specific matching substring() method 
.call("toString")  // Call toString() 
.get()     // Get the wrapped object, in this case a String 
संबंधित मुद्दे