我正在使用Spring 3.1.2.RELEASE和cglib加载时编织,我正在尝试使用具有自定义注释和注释参数的方法。
建议:
@Aspect
public class MyAdvice
{
@Around("execution(@com.mycompany.locking.Lock * *(@com.mycompany.locking.LockVal(*), ..)) " +
"&& args(batch) && @args(propertyToLock)"
public Object lockAndProceed(ProceedingJoinPoint pjp, Object batch, LockVal propertyToLock) throws Throwable {
//Do stuff....
pjp.proceed();
}
}
以下是我正在测试的课程:
public interface UpdateManager
{
public void processUpdate(MyBatchObject batch);
}
public class UpdateManagerImpl implements UpdateManager
{
@Lock
public void processUpdate(@LockVal("lockValue") MyBatchObject batch)
{
//Do stuff...
}
}
问题是我无法获得执行建议。如果我删除了切入点中的@args和args条件,那么建议就会触发,但是我必须通过ProceedingJoinPoint来获取我需要的参数。
为什么不提出建议?我做错了吗?
编辑:以下切入点作为Spring的独立程序工作:
@Aspect
public class MyAdvice
{
@Around("execution(@com.mycompany.locking.Lock * *(@com.mycompany.locking.LockVal(*), ..)) " +
"&& args(batch)"
public Object lockAndProceed(ProceedingJoinPoint pjp, Object batch) throws Throwable {
//Do stuff....
pjp.proceed();
}
}
但是,它在使用加载时编织的JBoss 6下不起作用。我想我的问题应该是,为什么它作为一个独立的程序工作,而不是在JBoss 6下?
答案 0 :(得分:2)
更新:我忘了提及@args()
并不是要匹配参数的注释,而是参数类型的注释,这不是你的意思想要,因此我不在这里使用。
您无法通过args()
绑定参数的注释,只能绑定参数本身。这意味着您只能通过反射访问参数的注释。您需要确定方法签名,从中创建一个Method
对象,然后迭代方法参数'注释。这是一个完整的代码示例:
package com.mycompany.locking;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Lock {}
package com.mycompany.locking;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface LockVal {
String value() default "";
}
package com.mycompany;
public class MyBatchObject {}
package com.mycompany;
public interface UpdateManager {
public void processUpdate(MyBatchObject batch);
}
package com.mycompany;
import com.mycompany.locking.Lock;
import com.mycompany.locking.LockVal;
public class UpdateManagerImpl implements UpdateManager {
@Lock
@Override
public void processUpdate(@LockVal("lockValue") MyBatchObject batch) {
System.out.println("Processing update");
}
public static void main(String[] args) {
UpdateManager updateManager = new UpdateManagerImpl();
updateManager.processUpdate(new MyBatchObject());
}
}
package com.mycompany.aop;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import com.mycompany.MyBatchObject;
import com.mycompany.locking.LockVal;
@Aspect
public class MyAspect {
@Pointcut("execution(@com.mycompany.locking.Lock * *(@com.mycompany.locking.LockVal (*), ..)) && args(batch)")
public void lockedMethod(MyBatchObject batch) {}
@Around("lockedMethod(batch)")
public Object lockAndProceed(ProceedingJoinPoint pjp, MyBatchObject batch) throws Throwable {
System.out.println(pjp);
System.out.println(batch);
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
Class<?> clazz = methodSignature.getDeclaringType();
Method method = clazz.getDeclaredMethod(methodSignature.getName(), methodSignature.getParameterTypes());
LockVal propertyToLock;
for (Annotation ann : method.getParameterAnnotations()[0]) {
if(LockVal.class.isInstance(ann)) {
propertyToLock = (LockVal) ann;
System.out.println(propertyToLock.value());
}
}
return pjp.proceed();
}
}
当我运行UpdateManagerImpl.main
时,我看到以下输出,正如预期的那样:
execution(void com.mycompany.UpdateManagerImpl.processUpdate(MyBatchObject))
com.mycompany.MyBatchObject@86f241
lockValue
Processing update
免责声明:我不是一个春天的人,我只是用普通的AspectJ来测试它,而不是Spring AOP。
答案 1 :(得分:1)
这不是一个解决方案,但应该更进一步:
我假设您在注释中输了一个拼写错误,您可能意味着@Aspect
而不是@Advice
?
我的建议是尝试这些:
一个。分离到命名点切口和要在切入点上应用的建议:
@PointCut("execution(@com.mycompany.locking.Lock * *(@com.mycompany.locking.LockVal(*), ..)) && args(batch) && @args(propertyToLock)")
public void mypointcut(Object batch, LockVal propertyToLock){}
@Around("mypointcut(batch, propertyToLock)"
public Object lockAndProceed(ProceedingJoinPoint pjp, Object batch, LockVal propertyToLock) throws Throwable {
//Do stuff....
pjp.proceed();
}
湾可能是args
表达式或@args
表达式导致问题 - 尝试保留一个并删除其他表达式并查看哪个组合有效。
℃。如果这不会缩小范围,另外一个选项可能是显式添加argNames
表达式,可能是参数名称正在被清除并且在运行时没有被名称匹配:
@PointCut("execution(@com.mycompany.locking.Lock * *(@com.mycompany.locking.LockVal(*), ..)) && args(batch) && @args(propertyToLock) && argNames="batch,test1,test2")
public void mypointcut(Object batch, LockVal propertyToLock){}