繁体   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