您的代码中有几个错误:
- Spring AOP 只能拦截 Spring 组件上的方法调用。您试图拦截的是局部变量的注释。即使是更强大的 AspectJ 也不能拦截任何有关局部变量的内容,只能拦截对类成员的读/写访问。因此,您尝试做的事情是不可能的。顺便说一句,这是糟糕的应用程序设计。为什么有人在尝试应用横切行为时想要依赖方法内部?方法内部需要频繁重构。建议:将注释放在方法上
public int sleep(String sleepHours)
.
- 您的注释在运行时是不可见的,因为您忘记添加元注释,例如
@Retention(RetentionPolicy.RUNTIME)
.
-
@args
是错误的切入点类型。它捕获带注释类型的方法参数。你想使用@annotation(com.aspect.Sleepable)
反而。
我认为你不应该尝试使用 Spring AOP 进行复制粘贴冷启动,而是阅读Spring AOP使用手册 https://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html第一的。我在这里解释的所有内容都可以在那里找到。
Update:所以根据你的评论,你只是在练习并试图编造一个例子@args()
。这是普通 AspectJ 中的一个。您可以在 Spring AOP 中以类似的形式轻松使用它。这@Before
建议向您展示如何将参数与其类上的注释进行匹配,@After
建议还展示了如何将相应的注释绑定到建议参数。
使用它的注释+类:
package com.company.app;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {}
package com.company.app;
@MyAnnotation
public class MyClass {}
驱动程序应用:
package com.company.app;
public class Application {
public static void main(String[] args) {
new Application().doSomething(new MyClass(), 11);
}
public String doSomething(MyClass myClass, int i) {
return "blah";
}
}
可以看到,这里我们使用了带注释的类MyClass
在方法参数中。这个可以搭配@args()
在以下方面。
Aspect:
package com.company.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import com.company.app.MyAnnotation;
@Aspect
public class MyAspect {
@Before("@args(com.company.app.MyAnnotation, ..)")
public void myBeforeAdvice(JoinPoint thisJoinPoint) {
System.out.println("Before " + thisJoinPoint);
}
@After("@args(myAnnotation, ..)")
public void myAfterAdvice(JoinPoint thisJoinPoint, MyAnnotation myAnnotation) {
System.out.println("After " + thisJoinPoint + " -> " + myAnnotation);
}
}
控制台日志:
Before call(String com.company.app.Application.doSomething(MyClass, int))
Before execution(String com.company.app.Application.doSomething(MyClass, int))
After execution(String com.company.app.Application.doSomething(MyClass, int)) -> @com.company.app.MyAnnotation()
After call(String com.company.app.Application.doSomething(MyClass, int)) -> @com.company.app.MyAnnotation()
当然,call()
连接点在 Spring AOP 中不可用,因此您只能看到两行日志输出。