मैं एक कस्टम एनोटेशन के साथ एनोटेटेड विधि के आसपास एक पॉइंटकट को परिभाषित करने की कोशिश कर रहा हूं। एनोटेशन में एक पैरामीटर है जिसे मैं पॉइंटकट परिभाषा में एक चेक शामिल करना चाहूंगा।

यह एनोटेशन है:

public @interface MyAnno {
  String[] types;
}

एनोटेशन कैसे लागू किया जा सकता है इसका एक उदाहरण:

public class MyClass {
  @MyAnno(types={"type1", "type2"})
  public void doSomething() {
    // ...
  }
  @MyAnno(types={"type3"})
  public void doSomethingElse() {
    // ...
  }
}

अब मैं दो पॉइंटकट परिभाषाएं चाहता हूं जो एनोटेशन की सामग्री के आधार पर उन दो विधियों का चयन करें।

एनोटेशन पर ही पॉइंटकट बनाना अपेक्षाकृत आसान है:

@Pointcut("@annotation(myAnno)")
public void pointcutAnno(MyAnno myAnno) {
}

@Pointcut("execution(* *(..)) && pointcutAnno(myAnno)")
public void pointcut(MyAnno myAnno) {
}

यह @MyAnno की हर घटना से मेल खाएगा। लेकिन मैं दो पॉइंटकट को कैसे परिभाषित कर सकता हूं, एक मिलान @MyAnno के साथ types जिसमें "type1" और दूसरा मिलान @MyAnno types के साथ "type3"

1
Francois Fernandes 23 नवम्बर 2017, 18:39

2 जवाब

सबसे बढ़िया उत्तर

वर्तमान में AspectJ अनुमत प्रकार के एनोटेशन मान के सबसेट के लिए एनोटेशन मान मिलान का समर्थन करता है। दुर्भाग्य से आप जिस सरणी प्रकार का उपयोग कर रहे हैं वह समर्थित नहीं है (वर्ग भी समर्थित नहीं है)। यह सुविधा 1.6.0 AspectJ README (https://eclipse में प्रलेखित है। org/aspectj/doc/released/README-160.html)। 'एनोटेशन वैल्यू मैचिंग' पर एक सेक्शन है। जैसा कि वहां वर्णित है, मूल मामलों के लिए वाक्यविन्यास वास्तव में काफी सहज है:

enum TraceLevel { NONE, LEVEL1, LEVEL2, LEVEL3 }

@interface Trace {
  TraceLevel value() default TraceLevel.LEVEL1;
}

aspect X {
  // Advise all methods marked @Trace except those with a tracelevel of none
  before(): execution(@Trace !@Trace(TraceLevel.NONE) * *(..)) {
    System.err.println("tracing "+thisJoinPoint);
  }
}

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

execution(@MyAnno(types={"type1"}) * *(..)) { // exactly and only 'type1'
execution(@MyAnno(types={"type1",..}) * *(..)) { // at least 'type1'

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

2
Andy Clement 24 नवम्बर 2017, 05:15

आप इसे सशर्त पॉइंटकट के साथ कर सकते हैं लेकिन उनमें एनोटेशन विशेषता पर रनटाइम टेस्ट शामिल होगा।

मूल पहलू सिंटैक्स:

pointcut p(MyAnno myAnno): execution(* *(..)) 
    && @annotation(myAnno) 
    && if(Arrays.stream(myAnno.types()).anyMatch("type1"::equals));

एनोटेशन आधारित पहलू सिंटैक्स:

@Pointcut("execution(* *(..)) && @annotation(myAnno) && if()")
public boolean pointcut(MyAnno myAnno) {
    return !Arrays.stream(myAnno.types()).anyMatch("type1"::equals);
}

दोनों उदाहरणों के लिए java.util.Arrays आयात करना न भूलें।

वर्तमान में, AspectJ संस्करण 1.8.13 के अनुसार, आप सरणी टाइप की गई एनोटेशन विशेषताओं पर पॉइंटकट अभिव्यक्तियों को स्थिर रूप से प्रतिबंधित नहीं कर सकते क्योंकि आप गैर-सरणी टाइप की गई विशेषताओं के साथ सक्षम होंगे, इसलिए इस समाधान में इसके बजाय एक रनटाइम परीक्षण शामिल होगा।

1
Nándor Előd Fekete 24 नवम्बर 2017, 06:30