2015-06-11 9 views
6

मेरे पास जावा 6 प्रोजेक्ट है जिसे जावा 8 में माइग्रेट किया जा रहा है। हमने बटन क्लिक करने जैसे कुछ उपयोगकर्ताओं के कार्यों को लॉग इन करने के लिए aspectj का उपयोग किया।Aspectj: लैम्बडा अभिव्यक्ति पर पॉइंटकट

button.addClickListener(new Button.ClickListener() { 
     @Override 
     public void buttonClick(Button.ClickEvent clickEvent) { 
      doSth(); 
     } 
    }); 

और poincut:

तो वहाँ इस तरह श्रोताओं हैं

@Pointcut("execution(public void Button.ClickListener.buttonClick(Button.ClickEvent))") 
public void buttonClick() {}; 

लेकिन चूंकि हम Java8 का उपयोग करेगा, श्रोताओं इस तरह होगा:

button.addClickListener(clickEvent -> doSth()); 

वहाँ है पहलू पॉइंटकट लिखने का कोई तरीका, ताकि यह नए श्रोताओं को संभाल सके?

+0

मुझे लगता है कि आपका 'पॉइंटकट' अभी भी काम कर रहा है क्योंकि आपने 'लम्बाडा' और 'बटन' का उपयोग करने के लिए 'addClickListener' को संशोधित किया है। क्लिक करें। क्लिक करें। बटन पर क्लिक करें' अभी भी रैमैन समान है। क्या आपने इसे भी संशोधित किया? –

+0

यह निश्चित रूप से काम नहीं कर रहा है। मैंने केवल लैम्ब्डा का उपयोग करने के लिए addClickListener को संशोधित किया। हां, यह अभी भी बटन का उपयोग करता है .ClickListener.button क्लिक करें लेकिन फ़ंक्शन को पॉइंटकट से पहले निष्पादित किया जाना चाहिए (जैसा कि: @Before ("बटनक्लिक()") कभी नहीं कहा जाता है। इसे गैर-लैम्ब्डा परिभाषा का उपयोग करने पर कहा जाता है। – Lete

+0

तो इसका तात्पर्य है कि AspectJ रनटाइम पर 'LambdaMetaFactory' द्वारा उत्पन्न श्रोता वर्ग के तरीकों को पैच करने में सक्षम नहीं है। लेकिन क्या यह' इंटरफ़ेस 'के' डिफ़ॉल्ट 'विधियों को संशोधित कर सकता है? इससे संभावित समाधान हो सकता है ... – Holger

उत्तर

2

मुझे लगता है कि समस्या यह है कि लैम्बडा वास्तव में किसी भी नाम के साथ किसी भी इंटरफ़ेस विधियों को लागू/ओवरराइड नहीं करते हैं, लेकिन एक अनाम विधि बनाते हैं। इस उदाहरण को देखो:

package de.scrum_master.app; 

public class Application { 
    protected static void doSomething() {} 

    public static void main(String[] args) { 
     Button button = new Button(); 
     button.addClickListener(new Button.ClickListener() { 
      @Override 
      public void buttonClick(Button.ClickEvent clickEvent) { 
       doSomething(); 
      } 
     }); 
     button.click(); 

     button = new Button(); 
     button.addClickListener(clickEvent -> doSomething()); 
     button.click(); 
    } 
} 

आप देख सकते हैं, दो बटन:

डमी बटन वर्ग, Vaadin के कुछ हिस्सों नकल हम यहाँ की जरूरत है:

package de.scrum_master.app; 

public class Button { 
    private ClickListener listener; 

    public void addClickListener(ClickListener listener) { 
     this.listener = listener; 
    } 

    public void click() { 
     System.out.println("Clicking button"); 
     listener.buttonClick(new ClickEvent()); 
    } 

    public static class ClickEvent {} 

    public static interface ClickListener { 
     public void buttonClick(ClickEvent clickEvent); 
    } 
} 

ड्राइवर आवेदन उदाहरण बनाए जाते हैं, एक शास्त्रीय अनाम वर्ग श्रोता के साथ, एक लैम्ब्डा श्रोता के साथ। दोनों बटन क्लिक किया हो, तो इसके परिणामस्वरूप कंसोल लॉग इस तरह दिखता है:

Clicking button 
Clicking button 

पहलू:

package de.scrum_master.aspect; 

import org.aspectj.lang.JoinPoint; 
import org.aspectj.lang.annotation.Aspect; 
import org.aspectj.lang.annotation.Before; 

@Aspect 
public class ButtonClickLogger { 
    @Before("execution(public void *..Button.ClickListener.buttonClick(*..Button.ClickEvent))") 
    public void logButtonClick(JoinPoint thisJoinPoint) { 
     System.out.println("Caught button click: " + thisJoinPoint); 
    } 

    @Before("within(*..Application)") 
    public void logAllInListener(JoinPoint thisJoinPoint) { 
     System.out.println(" " + thisJoinPoint); 
    } 

    @Before("execution(void *..lambda*(*..Button.ClickEvent))") 
    public void logButtonClickLambda(JoinPoint thisJoinPoint) { 
     System.out.println("Caught button click (lambda): " + thisJoinPoint); 
    } 
} 

पहले सलाह एक pointcut आपसे मिलते-जुलते उपयोग करता है। यह केवल शास्त्रीय श्रोता घोषणाओं को रोक सकता है।

दूसरी सलाह डीबगिंग उद्देश्यों के लिए है और यह दिखाने के लिए कि यहां बिल्ली क्या चल रहा है, ड्राइवर अनुप्रयोग के भीतर सभी जोड़ों को लॉग करता है।

अंतिम, लेकिन कम से कम नहीं, तीसरी सलाह लैम्बडा-आधारित श्रोताओं को रोकने के लिए एक कामकाज दिखाती है, जो डिबग आउटपुट से प्राप्त लैम्बडास के लिए जावा कंपाइलर नामकरण के बारे में ज्ञान पर निर्भर करती है। यह बहुत अच्छा नहीं है, लेकिन इस पल के लिए यह काम करता है। कृपया ध्यान दें कि buttonClick(..) का लैम्ब्डा संस्करण सार्वजनिक नहीं है, इसलिए यह void *..lambda* है, public void *..lambda* नहीं है। AspectJ साथ

कंसोल आउटपुट:

staticinitialization(de.scrum_master.app.Application.<clinit>) 
    execution(void de.scrum_master.app.Application.main(String[])) 
    call(de.scrum_master.app.Button()) 
    call(de.scrum_master.app.Application.1()) 
    staticinitialization(de.scrum_master.app.Application.1.<clinit>) 
    preinitialization(de.scrum_master.app.Application.1()) 
    initialization(de.scrum_master.app.Application.1()) 
    initialization(de.scrum_master.app.Button.ClickListener()) 
    execution(de.scrum_master.app.Application.1()) 
    call(void de.scrum_master.app.Button.addClickListener(Button.ClickListener)) 
    call(void de.scrum_master.app.Button.click()) 
Clicking button 
Caught button click: execution(void de.scrum_master.app.Application.1.buttonClick(Button.ClickEvent)) 
    execution(void de.scrum_master.app.Application.1.buttonClick(Button.ClickEvent)) 
    call(void de.scrum_master.app.Application.doSomething()) 
    execution(void de.scrum_master.app.Application.doSomething()) 
    call(de.scrum_master.app.Button()) 
    call(void de.scrum_master.app.Button.addClickListener(Button.ClickListener)) 
    call(void de.scrum_master.app.Button.click()) 
Clicking button 
    execution(void de.scrum_master.app.Application.lambda$0(Button.ClickEvent)) 
Caught button click (lambda): execution(void de.scrum_master.app.Application.lambda$0(Button.ClickEvent)) 
    call(void de.scrum_master.app.Application.doSomething()) 
    execution(void de.scrum_master.app.Application.doSomething()) 

अद्यतन: AspectJ के लिए एक इसी Bugzilla issue अब नहीं है। मैंने अभी इसे बनाया है। यह मेलिंग सूची पर हालिया चर्चा को भी इंगित करता है।

+0

कृपया मेरे अपडेट को नोट करें बगजिला लिंक – kriegaex

+0

यदि किसी और को एक समान समस्या का सामना करना पड़ता है, तो कुछ लैम्ब्डा भी स्थैतिक तरीकों का निर्माण करते हैं, जो वर्तमान में यह उत्तर ट्रैक नहीं करता है। –

+0

वैसे, लैम्बडास में स्थिर तरीकों के बारे में कोई सवाल नहीं था। क्या आप अधिक विशिष्ट होने पर ध्यान देंगे और नमूना कोड प्रदान करना? आप नमूना कोड के साथ अपनी समस्या का वर्णन करने वाला एक नया प्रश्न बना सकते हैं और यहां से लिंक कर सकते हैं। मैं आपकी तलाश करना चाहता हूं और मदद कर सकता हूं हाँ मैं। – kriegaex

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