当参数之一是vararg时,我无法使spring-AOP切入点工作。给定以下代码,我希望切入点会在测试中的两次调用中均被触发,但是在两种情况下均不会调用。我在同一个类的其他方法上有其他方面的工作,所以我知道这对我的测试或弹簧设置不是问题-它似乎与该方法隔离,唯一的变化是vararg。

方法声明:

SearchResults getRelation(final ClmUserContextFactory contextFactory, final CloudObjectId objectId,
            final Class<? extends CloudClass>... relationClasses) throws BmcClientException;


切入点声明:

@Around(value = "execution(com.a.b.SearchResults "
        + "com.a.b.BmcClmRestJsonClient.getRelation(com.a.b.ClmUserContextFactory, com.a.b.CloudObjectId, Class<? extends com.a.b.CloudClass>...))"
        + " && args(contextFactory, objectId, relationClasses)",
        argNames = "jp,contextFactory,objectId,relationClasses")
private SearchResults getRelationVarargs(ProceedingJoinPoint jp, ClmUserContextFactory contextFactory,
        CloudObjectId objectId,
        Class<? extends CloudClass>[] relationClasses)
        throws Throwable
{...}


测试电话:

bmcClmRestJsonClient.getRelation(contextFactory, objectId, new Class[] { CloudClass.class });

bmcClmRestJsonClient.getRelation(contextFactory, objectId);


编辑:

我可以确认,如果我从切入点和方法定义中删除了定义的vararg部分(即,删除了所有的“ ...”和“ []”),则它可以工作,因此,这肯定与它们有关。如果将“ ...”替换为“ []”,它也将不起作用。

最佳答案

我不是Spring用户,但是我使用了AspectJ进行了此尝试,同时使用了代码样式和注释样式语法。对我来说,它可以工作,因此,我认为如果切入点定义正确,它也应该对您有用。

更新:我也认为您的建议方法必须是公开的,而不是私有的。

示例驱动程序应用程序:

package de.scrum_master.app;

public class Application {
    public static void main(String[] args) {
        System.out.println("Starting application");
        doSomething(11, String.class, String.class);
        System.out.println("Stopping application");
    }

    public static boolean doSomething(final int number, final Class<? extends String>... classes) {
        System.out.println("Doing something");
        return true;
    }
}


代码样式方面:

package de.scrum_master.aspect;

import de.scrum_master.app.Application;

public aspect CodeStyleAspect {
    boolean around(int number, Class<? extends String>[] classes) :
        execution(boolean Application.doSomething(int, Class<? extends String>...)) &&
        args(number, classes)
    {
        System.out.println(this.getClass().getName());
        System.out.println(thisJoinPointStaticPart);
        System.out.print("number = " + number + ", classes = { ");
        for (Class<? extends String> clazz : classes)
            System.out.print(clazz.getName() + ", ");
        System.out.println("}");
        return proceed(number, classes);
    }
}


注释样式方面:

package de.scrum_master.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AnnotationStyleAspect {
    @Around(
        "execution(boolean de.scrum_master.app.Application.doSomething(int, Class<? extends String>...)) &&" +
        "args(number, classes)"
    )
    public Object myAdvice(ProceedingJoinPoint thisJoinPoint, int number, Class<? extends String>[] classes) throws Throwable {
        System.out.println(this.getClass().getName());
        System.out.println(thisJoinPoint.getStaticPart());
        System.out.print("number = " + number + ", classes = { ");
        for (Class<? extends String> clazz : classes)
            System.out.print(clazz.getName() + ", ");
        System.out.println("}");
        return thisJoinPoint.proceed(new Object[] { number, classes });
    }
}


样本输出在两个方面都处于活动状态:

Starting application
de.scrum_master.aspect.CodeStyleAspect
execution(boolean de.scrum_master.app.Application.doSomething(int, Class[]))
number = 11, classes = { java.lang.String, java.lang.String, }
de.scrum_master.aspect.AnnotationStyleAspect
execution(boolean de.scrum_master.app.Application.doSomething(int, Class[]))
number = 11, classes = { java.lang.String, java.lang.String, }
Doing something
Stopping application


如您所见,这两个方面基本上都以相同的方式工作,并产生相等的结果。

09-10 09:44
查看更多