[英]Spring AOP pointcut not working with varargs
I am having trouble getting a spring-AOP pointcut to work when one of the parameters is a vararg. 当参数之一是vararg时,我无法使spring-AOP切入点工作。 Given the below code I would have expected the pointcut to be triggered on both calls from my test, however it is not called in either case.
给定以下代码,我希望测试中的两次调用都会触发切入点,但是无论哪种情况都不会调用切入点。 I have other aspects working on other methods in the same class, so I know it is not a problem with my testing or spring setups - it appears isolated to this method and the only thing unique about it is the vararg.
我在同一个类的其他方法上有其他方面的工作,所以我知道这对我的测试或spring设置不是问题-它似乎与该方法隔离,唯一的区别是vararg。
Method declaration: 方法声明:
SearchResults getRelation(final ClmUserContextFactory contextFactory, final CloudObjectId objectId,
final Class<? extends CloudClass>... relationClasses) throws BmcClientException;
Pointcut declaration: 切入点声明:
@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
{...}
Calls from test: 测试电话:
bmcClmRestJsonClient.getRelation(contextFactory, objectId, new Class[] { CloudClass.class });
bmcClmRestJsonClient.getRelation(contextFactory, objectId);
EDIT: 编辑:
I can confirm that if I remove the vararg part of the definition (ie remove all '...' and '[]') from the pointcut and method definitions it works, so it definitely appears to be something to do with those. 我可以确认,如果我从切入点和方法定义中删除了定义的vararg部分(即,删除了所有的“ ...”和“ []”),则它确实起作用,因此,这肯定与它们有关。 It also does not work if I replace the '...' with '[]'.
如果将“ ...”替换为“ []”,它也将不起作用。
I am not a Spring user, but I tried this with AspectJ, both with code-style and annotation-style syntax. 我不是Spring用户,但是我使用了AspectJ进行了此尝试,同时使用了代码样式和注释样式语法。 For me it works, so I assume it should also work for you if your pointcut definition is correct.
对我来说,它可以工作,因此,我认为如果切入点定义正确,它也应该对您有用。
Update: I also think your advice method must be public, not private. 更新:我也认为您的建议方法必须是公开的,而不是私有的。
Sample driver application: 示例驱动程序应用程序:
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;
}
}
Code-style aspect: 代码样式方面:
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);
}
}
Annotation-style aspect: 注释样式方面:
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 });
}
}
Sample output with both aspects active: 样本输出在两个方面都处于活动状态:
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
As you can see, both aspects basically work the same way and yield equivalent results. 如您所见,这两个方面基本上都以相同的方式工作,并产生相等的结果。
Whilst I am yet to find a solution, there is a work-around - you can get the arguments from the join point. 虽然我还没有找到解决方案,但是有一种解决方法-您可以从连接点获取参数。 The following is what I have decided on:
以下是我已决定的内容:
@Around(value = "execution(com.a.b.SearchResults "
+ "com.a.b.BmcClmRestJsonClient.getRelation(*, *, ..))")
public SearchResults getRelationVarargs(ProceedingJoinPoint jp)
And I extract the arguments from the join point as follows: 然后从连接点提取参数,如下所示:
Object[] args = jp.getArgs();
ClmUserContextFactory contextFactory = (ClmUserContextFactory) args[0];
CloudObjectId objectId = (CloudObjectId) args[1];
Class<? extends CloudClass>[] relationClasses = null;
if (args.length == 3)
{
relationClasses = (Class<? extends CloudClass>[]) args[2];
}
This obviously would not be good enough if you needed to specify the arguments for the pointcut in order for it to cut in the right places - luckily for me that is not the case. 如果您需要为切入点指定参数以使其切入正确的位置,那么这显然不够好-幸运的是,事实并非如此。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.