2012-05-17 15 views
14

मैं कुछ तरीकों से उत्पन्न कुछ मूल्यों के साथ एनोटेशन प्रदान करना चाहता हूं।गतिशील तरीके से प्रदान किए गए जावा एनोटेशन मान

मैं इस कोशिश की अब तक:

public @interface MyInterface { 
    String aString(); 
} 

@MyInterface(aString = MyClass.GENERIC_GENERATED_NAME) 
public class MyClass { 

    static final String GENERIC_GENERATED_NAME = MyClass.generateName(MyClass.class); 

    public static final String generateName(final Class<?> c) { 
     return c.getClass().getName(); 
    } 
} 

सोचा GENERIC_GENERATED_NAMEstatic final है, यह शिकायत है कि

एनोटेशन विशेषता MyInterface.aString के लिए मूल्य एक निरंतर अभिव्यक्ति

होना चाहिए

तो इसे कैसे प्राप्त करें?

उत्तर

14

एनोटेशन में उपयोग की जाने वाली स्ट्रिंग को गतिशील रूप से उत्पन्न करने का कोई तरीका नहीं है। संकलक संकलन समय पर RetentionPolicy.RUNTIME एनोटेशन के लिए एनोटेशन मेटाडेटा का मूल्यांकन करता है, लेकिन GENERIC_GENERATED_NAME रनटाइम तक ज्ञात नहीं है। और आप एनोटेशन के लिए जनरेटेड मानों का उपयोग नहीं कर सकते हैं जो RetentionPolicy.SOURCE हैं क्योंकि उन्हें संकलन समय के बाद छोड़ दिया जाता है, इसलिए उन उत्पन्न मूल्य कभी ज्ञात नहीं होंगे।

+0

ठीक है, तो मैं समझता हूं कि इसे एनोटेशन का उपयोग करके संबोधित नहीं किया जा सकता है, है ना? शायद मुझे संकलन से पहले कुछ उपकरण चलाने होंगे और जावा स्रोत को पूरा करना होगा। कोई अन्य सुझाव? – thelost

+0

@ टेलोस्ट मैंने कभी भी ईमानदार होने के लिए इतना कुछ नहीं देखा है। मुझे आज अपने खाली समय में थोड़ा सा देखने दो और मैं आप पर वापस आने की कोशिश करूंगा। –

4

समाधान इसके बजाय एक एनोटेटेड विधि का उपयोग करना है। डायनामिक वैल्यू प्राप्त करने के लिए उस विधि को कॉल करें (प्रतिबिंब के साथ)।

उपयोगकर्ता के नजरिए से हम होगा:

@MyInterface 
public class MyClass { 
    @MyName 
    public String generateName() { 
     return MyClass.class.getName(); 
    } 
} 

एनोटेशन ही

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
public @interface @MyName { 
} 

इन टिप्पणियों को दोनों के लिए देखने को लागू करने के रूप में परिभाषित किया जाएगा बल्कि सीधी-सपाट है।

// as looked up by @MyInterface 
Class<?> clazz; 

Method[] methods = clazz.getDeclaredMethods(); 
if (methods.length != 1) { 
    // error 
} 
Method method = methods[0]; 
if (!method.isAnnotationPresent(MyName.class)) { 
    // error as well 
} 
// This works if the class has a public empty constructor 
// (otherwise, get constructor & use setAccessible(true)) 
Object instance = clazz.newInstance(); 
// the dynamic value is here: 
String name = (String) method.invoke(instance); 
+0

आपके मामले में, शायद एक स्थिर विधि का भी उपयोग करें। प्रतिबिंब के माध्यम से इसे कॉल करने के लिए, http://stackoverflow.com/a/2467562/1068385 देखें – Arvidaa

0

दूसरों की तरह गतिशील रूप से एनोटेशन के गुणों को संशोधित करने का कोई तरीका नहीं है। फिर भी यदि आप इसे प्राप्त करना चाहते हैं, तो ऐसा करने के दो तरीके हैं।

  1. एनोटेशन में संपत्ति को अभिव्यक्ति सौंपें और जब भी आप एनोटेशन पुनर्प्राप्त करते हैं तो उस अभिव्यक्ति को संसाधित करें। आपके मामले में अपनी एनोटेशन

    @MyInterface हो सकता है (aString = "objectA.doSomething (args1, args2)")

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

  1. यह हम जो चाहते हैं उसे करने का एक हैकी तरीका है। जावा एक निजी चर स्टोर करता है जो वर्ग/फ़ील्ड/विधि पर एनोटेशन का नक्शा बनाए रखता है। आप प्रतिबिंब का उपयोग कर सकते हैं और उस मानचित्र को पकड़ सकते हैं। तो पहली बार एनोटेशन को संसाधित करते समय, हम अभिव्यक्ति को हल करते हैं और वास्तविक मान पाते हैं। फिर हम आवश्यक प्रकार की एक एनोटेशन ऑब्जेक्ट बनाते हैं।हम एनोटेशन की संपत्ति पर वास्तविक मूल्य (जो स्थिर है) के साथ नव निर्मित एनोटेशन डाल सकते हैं और पुनर्प्राप्त मानचित्र में वास्तविक एनोटेशन को ओवरराइड कर सकते हैं।

जिस तरह से जेडके एनोटेशन मानचित्र स्टोर करता है वह जावा संस्करण निर्भर है और यह विश्वसनीय नहीं है क्योंकि यह उपयोग के लिए खुला नहीं है (यह निजी है)।

आप यहां एक संदर्भ कार्यान्वयन पा सकते हैं।

https://rationaleemotions.wordpress.com/2016/05/27/changing-annotation-values-at-runtime/

पी.एस: मैं प्रयास नहीं किया है और दूसरी विधि का परीक्षण किया।

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