2017-03-06 90 views
1
@Before(value="@annotation(com.aspect.Loggable)",argNames="taskId") 

public void logEmail(JoinPoint joinPoint) { 

    System.out.println("@Before is running!"); 
    System.out.println("hijacked : " + joinPoint.getSignature().getName()); 
    System.out.println("******"); 
} 

我有一個pointCut方法sendEmail()與自定義註釋。春天AOP - 如何獲得父(方法)的註釋方法

該方法sendEmail()從我們的應用程序中的不同位置調用。

就像我們從paymentApproved()付款管理器支付方式批准時,我們呼籲sendEmail。 當任務完成時,我們從任務管理器的taskComplete()方法調用sendEmail。

我必須找出觸發sendEmail的事件。

我在paymentManager的paymentApproved()上應用了自定義註釋@EVENT("PAYMENT"),在taskComplete()上應用了10任務管理器的方法。

我怎樣才能得到@EVENT在​​方面的價值。

回答

0

您可以訪問收到它的註釋作爲參數。事情是這樣的:

@Before(value="@annotation(EVENT)",argNames="taskId") 

public void logEmail(JoinPoint joinPoint, Event event) { 

    // do what you need with event. For example, if the field is called value you can do this: 
    if ("PAYMENT".equals(event.value())) { 
     // do sth 
    } 

    System.out.println("@Before is running!"); 
    System.out.println("hijacked : " + joinPoint.getSignature().getName()); 
    System.out.println("******"); 
} 
+0

這不是OP問題的答案。他希望從執行'sendEmail'的另一個連接點獲取事件註釋。 – kriegaex

+0

如果我不明白它的錯誤,他在調用'sendEmail'的方法中使用相同的批註,並且切入點用於此批註 – mlg

+0

我想你確實明白它是錯誤的。他希望在'sendEmail'上仍然有一個切入點,並從那裏訪問調用者的註釋。我知道將切入點改爲調用方法也可以以間接方式解決問題,但是如果使用不調用電子郵件方法但執行其他操作的事件註釋來註釋方法,該怎麼辦?看我即將到來的解決方 – kriegaex

1

腳手架:

對不起,我不喜歡全部大寫的類名,我也用我自己的包名作爲例子,因爲我的模板已經生成它們。

package de.scrum_master.app; 

import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 

@Retention(RetentionPolicy.RUNTIME) 
public @interface Loggable {} 
package de.scrum_master.app; 

import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 

@Retention(RetentionPolicy.RUNTIME) 
public @interface Event { 
    String value(); 
} 

驅動程序:

這是純Java的,因爲我不是一個Spring用戶。試想一下,它是一個或多個@Component s。

另請注意,在一種情況下,sendEmail()未通過由@Event註解的方法調用。這不應該觸發該方面,只有來自注釋方法的兩個調用。

package de.scrum_master.app; 

public class Application { 
    public static void main(String[] args) { 
    Application application = new Application(); 
    application.doSomething(); 
    application.paymentApproved(); 
    application.taskComplete(); 
    } 

    public void doSomething() { 
    sendEmail(); 
    } 

    @Event("paymentApproved") 
    public void paymentApproved() { 
    sendEmail(); 
    } 

    @Event("taskComplete") 
    public void taskComplete() { 
    sendEmail(); 
    } 

    @Loggable 
    public void sendEmail() {} 
} 

看點:

你的切入點要表達的:由@Event註釋的方法控制流內的@Loggable註釋捕捉方法。控制流程可以用cflow()cflowbelow()切入點表示。

package de.scrum_master.aspect; 

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

import de.scrum_master.app.Event; 

@Aspect 
public class LogAspect { 
    @Before(
    "@annotation(de.scrum_master.app.Loggable) &&" + 
    "execution(* *(..)) &&" + // only needed for AspectJ, not for Spring AOP 
    "cflow(@annotation(event))" 
) 
    public void logEmail(JoinPoint thisJoinPoint, Event event) { 
    System.out.println(thisJoinPoint + " -> " + event); 
    } 
} 

控制檯日誌:

execution(void de.scrum_master.app.Application.sendEmail()) -> @de.scrum_master.app.Event(value=paymentApproved) 
execution(void de.scrum_master.app.Application.sendEmail()) -> @de.scrum_master.app.Event(value=taskComplete) 

更新:如果您使用完整的AspectJ(例如,通過裝載時織入)代替Spring AOP的,你剛纔也可以使用一個call()切入點,並從那裏獲得封閉連接點的靜態信息。那麼@Event註釋就沒有必要了。但是Spring AOP只是「AOP lite」,不支持call()

+0

嗨kriegaex感謝您的迴應:這是excat我需要的,但對於「cflow」它給了我錯誤:「不支持的切入點原語'cflow'」。 我搜索spring不支持這個唯一的aspectJ支持。 –

+1

是的,我忘了這一點,因爲我從來沒有使用過Spring AOP。但是,如果您確實需要'cflow()',您仍然可以決定在Spring應用程序中使用AspectJ LTW。 [本章](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-using-aspectj)介紹瞭如何配置它。正如我所說的:Spring AOP是「AOP lite」。 ;-)如果你想堅持Spring AOP,你也可以選擇@mlg的間接解決方案。 – kriegaex