为Spring AOP注释创建切入点,以将注释放在类上,并对类中的每个方法执行建议



我想在类级别进行注释,该注释将对注释类中的每个方法执行建议。 这可能吗。

示例:我想用@DoSomethingForMe注释OmniDemoService,我希望method1method2在执行前记录">看着我">

这个例子不起作用,我不知道为什么。当我将 Pointcut 转换为 Around 并将其与注释一起使用(也将注释 ElementType 更改为方法)时,一切都在方法级别工作。 所以我认为这是错误定义的切入点。

注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DoSomethingForMe {
}

建议:

@Aspect
@Component
public class DoSomethingForMeAdvice {
private static final Logger logger = LoggerFactory.getLogger(DoSomethingForMeAdvice.class);
@Pointcut("execution(public * *(..)) && @annotation(DoSomethingForMe)")
public void anyAnnotatedMethod() {
}
@Before("anyAnnotatedMethod()")
public void acquireExecution() {
logger.info("look at me");
}
}

用法:

@Service
@DoSomethingForMe
public class OmniDemoService {
private static final Logger logger = LoggerFactory.getLogger(OmniDemoService.class);
public void method1() {
logger.info("---1---");
}

public void method2() {
logger.info("---2---");
}
}

您的问题是您将切入点定义与建议混淆了。

切入点是瞄准,建议执行实际你想要的执行。比如

@Pointcut("@annotation(com.omnidemo.advice.DoSomethingForMe)")
public void anyAnnotatedMethod() {
}

@Before("anyAnnotatedMethod()")
public void logMethodCall(JoinPoint jp) {
String methodName = jp.getSignature().toShortString();
logger.info("Executing: " + methodName);
}

该问题的解决方案是使用 in 进行切入点

@Pointcut("@within(DoSomethingForMe)")
public void anyAnnotatedMethod() {
}
@Before("anyAnnotatedMethod()")
public void acquireExecution() {
logger.info("look at me");
}

@J Asgarov在评论中提供的解决方案

查看 AspectJ 快速参考对@annotation()的看法:

主题具有类型批注的任何连接点SomeAnnotation

您使用了@annotation(DoSomethingForMe)但方法执行的"主题"是方法。因此,这意味着任何方法都带有注释@DoSomethingForMe。

使用@this(DoSomethingForMe)@target(DoSomethingForMe)

感谢 kriegaex 指出@this@target必须在运行时进行评估,这会严重污染代码库(即检查每个方法)。所以下一个方法更好:


如果您查看有关类型模式的 AspectJ 手册部分,您会发现您可以直接注释类型。还请记住使用完全限定的类名。所以这将是:

execution(public * (@com.path.DoSomethingForMe *).*(..))

另外,如果您有如此简单的切入点并且不需要重用它,我认为您可以放弃其他方法并直接在建议中使用它:

@Before("execution(public * (@com.path.DoSomethingForMe *).*(..))")

它说:"在执行用@com.path.DoSomethingForMe注释的任何类型的公共方法之前",其中"在执行方法之前"是指"在方法内部,开始时"。


或者,如果这个切入点对你来说看起来有点太复杂了,你可以像这样分开注释匹配和方法匹配,正如 J Asgarov 在他的评论中所建议的那样:

@Before("execution(public * *(..)) && @within(com.path.DoSomethingForMe)")

相关内容

  • 没有找到相关文章