SpringAspectJ,方法执行前的切入点,其中方法或类被注释
我试图通过Spring Aop AspectJ样式获取注释的值,其中注释可以位于类或方法上。我尝试了很多不同的方法,但只有在方法上有注释时,我才能让它工作。我真的很想在类上注释一次,但建议类的所有方法,并在建议中访问类注释的值。这就是我的结局: 注释:SpringAspectJ,方法执行前的切入点,其中方法或类被注释,spring,aspectj,spring-aop,Spring,Aspectj,Spring Aop,我试图通过Spring Aop AspectJ样式获取注释的值,其中注释可以位于类或方法上。我尝试了很多不同的方法,但只有在方法上有注释时,我才能让它工作。我真的很想在类上注释一次,但建议类的所有方法,并在建议中访问类注释的值。这就是我的结局: 注释: @Inherited @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotati
@Inherited
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "";
}
方面:
@Aspect
public class MyAspect {
@Pointcut("execution(@com.myco.MyAnnotation * com.myco.somepackage..*.*(..))")
public void atExecution() { }
@Before("atExecution() && @annotation(myAnnotation)")
public void myAdvice(JoinPoint joinPoint, MyAnnotation myAnnotation) {
...
}
}
有什么想法吗?谢谢。简短回答
虽然您可以制定一个切入点,该切入点将同时匹配直接注释的方法和注释类型的方法,但您不能在绑定注释值(即在注释代码中使用注释值)的位置生成切入点和/或建议
一些细节
要组合两个单独的切入点(ATExecutionFannotatedMethod
和ATExecutionOfMethodsofNotatedClass
),我们必须使用OR(|
)构造。由于OR构造不能保证两个注释绑定中的任何一个在通知执行时出现,因此它们都会导致编译错误(绑定不一致)。
您仍然可以在单独的通知中处理这两种情况,也可以将实际的通知代码委托给一个通用方法以避免重复。在这种情况下,您需要注意类型和方法都使用@MyAnnotation
进行注释的情况,因为这将匹配两个切入点,并将导致您的方法被两个通知双重通知,因此您的通用通知处理代码将执行两次
两者结合
如果需要将这两种情况结合起来,同时避免双重通知目标代码,则需要在方法级注释和类级注释之间设置优先级。基于特殊性原则,我建议继续采用方法级注释优先于类级注释的方法。您的外观如下所示:
@Aspect
public class MyCombinedAspect {
@Pointcut("execution(@com.myco.MyAnnotation * com.myco.somepackage..*.*(..))")
public void atExecutionOfAnnotatedMethod() {}
@Pointcut("execution(* (@com.myco.MyAnnotation com.myco.somepackage..*).*(..))")
public void atExecutionOfMethodsOfAnnotatedClass() {}
@Before("atExecutionOfAnnotatedMethod() && !atExecutionOfMethodsOfAnnotatedClass() && @annotation(myAnnotation)")
public void myAdviceForMethodAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
handleBeforeExecution(joinPoint, myAnnotation);
}
@Before("atExecutionOfMethodsOfAnnotatedClass() && !atExecutionOfAnnotatedMethod() && @this(myAnnotation)")
public void myAdviceForTypeAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
handleBeforeExecution(joinPoint, myAnnotation);
}
@Before("atExecutionOfMethodsOfAnnotatedClass() && atExecutionOfAnnotatedMethod() && @annotation(myMethodAnnotation)")
public void myAdviceForDoublyAnnotated(JoinPoint joinPoint, MyAnnotation myMethodAnnotation) {
handleBeforeExecution(joinPoint, myMethodAnnotation);
}
protected void handleBeforeExecution(JoinPoint joinPoint, MyAnnotation myAnnotation) {
System.out.println(myAnnotation.value());
}
谢谢你的回复。非常详细。所以我想澄清一下。我可以用两个不同的建议来做这件事,但是需要注意不要同时注释类和方法。(这将很难执行)。再次感谢!不,让我澄清一下。注释类或方法就足够了。但是我们不能强制开发人员不同时注释类和方法。在这种情况下,我们希望方法注释生效。因此,我们有3条建议来处理3种情况,顺序是:1-当仅对方法进行注释时,2-当仅对类进行注释时,3-当对方法和类进行注释时,在这种情况下,方法注释的值传递给委托方法。这三个建议都代表了同样的方法来做这项工作,坚持干燥的原则。我的回答中的第二个方面与我在之前的评论中描述的方式相同。希望这能消除最终的困惑,明白了。再次感谢所有的细节。真的很有帮助。
@Aspect
public class MyCombinedAspect {
@Pointcut("execution(@com.myco.MyAnnotation * com.myco.somepackage..*.*(..))")
public void atExecutionOfAnnotatedMethod() {}
@Pointcut("execution(* (@com.myco.MyAnnotation com.myco.somepackage..*).*(..))")
public void atExecutionOfMethodsOfAnnotatedClass() {}
@Before("atExecutionOfAnnotatedMethod() && !atExecutionOfMethodsOfAnnotatedClass() && @annotation(myAnnotation)")
public void myAdviceForMethodAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
handleBeforeExecution(joinPoint, myAnnotation);
}
@Before("atExecutionOfMethodsOfAnnotatedClass() && !atExecutionOfAnnotatedMethod() && @this(myAnnotation)")
public void myAdviceForTypeAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
handleBeforeExecution(joinPoint, myAnnotation);
}
@Before("atExecutionOfMethodsOfAnnotatedClass() && atExecutionOfAnnotatedMethod() && @annotation(myMethodAnnotation)")
public void myAdviceForDoublyAnnotated(JoinPoint joinPoint, MyAnnotation myMethodAnnotation) {
handleBeforeExecution(joinPoint, myMethodAnnotation);
}
protected void handleBeforeExecution(JoinPoint joinPoint, MyAnnotation myAnnotation) {
System.out.println(myAnnotation.value());
}