在建议执行两次之前...相同的连接点列出两次相同的方法,因此它被调用两次

时间:2015-02-12 03:00:23

标签: java aspectj aop aspect

我们在使用自定义注释的“建议之前”实现,以便仅在(对此问题不感兴趣)业务逻辑适用时才执行某些方法。

我们看到每次调用方法时都会调用两次方面。

调试它我看到Cglib2AopProxy$CglibMethodInvocation.proceed有一个名为interceptorsAndDynamicMethodMatchers的数组。这个数组列出了PointCut ("RequiresX")两次。

这是连接点:

@Before(@annotation(requiresX)”)
public Object process(ProceedingJoinPoint joinPoint, RequiresACL requiresX) throws Throwable
{
    Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
    log.info(" method:" + method.getName());

    // do business logic of the aspect…

    log.info(" joinPoint.proceed with call to " + method.getName());
 }

这是我们的自定义注释

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.Method)
public @interface RequiresX {
}

这是我们可以拦截的方法:

@RequiresX()
public String someMethod() {    
    ....
}

这看起来很香草,但显然我做错了什么。任何关于如何每次通话只执行一次建议的建议将不胜感激。

2 个答案:

答案 0 :(得分:6)

你应该打印Pointcut并看到如下问题:

@Before(@annotation(requiresX)”)
public Object process(ProceedingJoinPoint joinPoint, RequiresACL requiresX) throws Throwable
{

    log.info(" pointcut:" + joinPoint.getKind());
    // do business logic of the aspect…


 }

它会打印出类似的问题:

pointcut:method-call 
pointcut:method-execution

因此,您应该将Pointcut更改为:

@Before(@annotation(RequiresX) && execution(@RequiresX * *.*(..)))

答案 1 :(得分:1)

我们通过试验和错误以及通过以下帖子找到答案:http://forum.spring.io/forum/spring-projects/aop/25729-advice-is-called-twice-with-aop-auto-proxy-configuration

底线是我们在方面类上有一个@Aspect注释,以及在Spring XML文件中指定方面。不要两者兼顾。