簡體   English   中英

用於子類中自定義注釋的Spring AOP Pointcut表達式

[英]Spring AOP Pointcut expression for custom annotation in subclass

我正在進行日志記錄方面的工作,該方面需要攔截所有使用自定義注釋進行注釋的類和方法。

以下是可以在類和方法上進行注釋的自定義注釋類:

@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Loggable {
    LogLevel value();
}

我正在使用這些切入點表達式來截取帶有注釋@Loggable方法和類, 方法和類適用於所有簡單類,但不適用於擴展或實現的類。

//Works for annotation @Loggable on class level
@Pointcut("execution(* *(..)) &&  within(@com.logger.Loggable *)")
public void classAnnotationLogger() {
}

//Working for methods annotated with @Loggable
@Before(value = "@annotation(loggable)", argNames = "jp, loggable")
public void logBeforeAdvice(JoinPoint jp, Loggable loggable) {
  ..
  ..
}

下面是超類的代碼

@Component
@Loggable(LogLevel.INFO)
public abstract class Processor{
  public void process(){
      readProcess();
  }

  public abstract void readProcess();
}

下面是子類的代碼

@Service
@Loggable(LogLevel.INFO)
public class MyServiceProcessor extends Processor {

  @Override
  public void readProcess(){
    ...
    ...
  }
}

在應用程序中,通過執行readProcess()來調用

Processor processor = applicationContext.getBean(MyServiceProcessor.class);
processor.readProcess();

即使我在ProcessorMyServiceProcessor上具有@Loggable ,當readProcess時,該建議也不會被調用。

但是建議是為process()而不是readProcess

當在任何類或方法上應用注解@Logabble時,如何編寫也會截取對任何子類方法的調用的切入點表達式?

好吧,首先

@Pointcut("execution(* *(..)) &&  within(@com.logger.Loggable *)")
public void classAnnotationLogger() {}

只是切入點,而不是建議,因此除非您也有使用切入點的建議,否則它不會做任何事情。 您尚未發布這樣的建議,所以我只能推測。

其次,您沒有提供任何由以下代碼觸發的示例代碼

@Before(value = "@annotation(loggable)", argNames = "jp, loggable")
public void logBeforeAdvice(JoinPoint jp, Loggable loggable) {}

根本沒有注釋方法。 您的示例代碼僅顯示帶注釋的類。

至於子類上的@Loggable批注,由於它的基類已經帶有相同的批注並且該批注是@Inherited ,因此它不是必需的。 這適用於類的注釋,但不適用於方法或接口的注釋,請參閱我的其他答案以獲取解釋和可能的解決方法。

您的這個示例應該可以正常工作,我看不出為什么它不起作用的原因:

Processor processor = applicationContext.getBean(MyServiceProcessor.class);
processor.readProcess();

但是內部對readProcess()調用(等效於this.readProcess() )將無法工作:

public void process() {
    readProcess();
}

這是因為Spring AOP是依賴於JDK動態代理(用於接口)或CGLIB代理(用於類)的基於代理的“ AOP lite”框架。 但是對this.someMethod()調用不會通過任何類型的代理進行路由,因此它們不能被Spring方面攔截。 這是記錄的行為。 如果您想克服此限制,並將方面也應用到內部方法調用中,請使用此處所述的成熟的AspectJ。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM