spring - 如何使用带注释的参数将参数传递给 Spring AOP 建议?

标签 spring aop aspectj spring-aop

我正在使用带有 cglib 加载时编织的 Spring 3.1.2.RELEASE,并且我正在尝试获得使用具有自定义注释和注释参数的方法的建议。

建议:

@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();
   }
}

这是我正在测试的类(class):
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 下运行?

最佳答案

更新:我忘了提 @args()不是要匹配参数的注释,而是参数类型的注释,这不是您想要的,因此我在这里不使用。

您不能通过 args() 绑定(bind)参数的注释。 ,只有参数本身。这意味着您只能通过反射访问参数的注释。您需要确定方法签名,创建 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

免责声明:我不是 Spring 人,我只是用普通的 AspectJ 测试了这个,而不是 Spring AOP。

关于spring - 如何使用带注释的参数将参数传递给 Spring AOP 建议?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16617374/

相关文章:

java - 如何在JUnit中的@Rule中使用@Values字段?

java - 包括与 Proxetta 的额外接口(interface)

java - Spring 推荐 : proxying mechanism vs @Transactional on class or interface

java - JNLP/Webstart - 设置环境变量

java - AspectJ 和 Spring LTW 在向上转换时不起作用

java - CrudRepository,无法使用 IdClass 保存具有复合主键的实体

java - Spring 连接池问题

java - 在没有 Proxy 类的情况下使用方面注入(inject) InvocationHandlers

hibernate - 如何配置 Spring Boot 应用程序以使用 aspectj 事务?

java - 如何为 MockServer 的相同请求设置不同的响应?