복붙노트

[SPRING] 주석이 달린 매개 변수로 Spring AOP advice에 인수를 전달하려면 어떻게해야합니까?

SPRING

주석이 달린 매개 변수로 Spring AOP advice에 인수를 전달하려면 어떻게해야합니까?

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를 통해 필요한 매개 변수를 가져와야합니다.

왜 조언은 발사되지 않습니까? 내가 뭐 잘못 했어요?

편집 : 다음 pointcut은 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이 아닌 독립 실행 형 프로그램으로 작동하는 이유는 무엇입니까?

해결법

  1. ==============================

    1.업데이트 : @args ()는 매개 변수의 주석과 일치하는 것이 아니라 매개 변수 유형의 주석 (원하는 방식이 아니므로 여기서는 사용하지 않음)을 언급하는 것을 잊었습니다.

    업데이트 : @args ()는 매개 변수의 주석과 일치하는 것이 아니라 매개 변수 유형의 주석 (원하는 방식이 아니므로 여기서는 사용하지 않음)을 언급하는 것을 잊었습니다.

    args ()를 통해 매개 변수의 주석을 바인딩 할 수는 없으며 매개 변수 자체 만 바인딩 할 수 있습니다. 즉, 리플렉션을 통해 매개 변수의 주석에만 액세스 할 수 있습니다. 메서드 시그니처를 결정하고이 메서드에서 메서드 개체를 만든 다음 메서드 매개 변수의 주석을 반복해야합니다. 다음은 전체 코드 샘플입니다.

    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 녀석이 아닙니다. 스프링 AOP가 아닌 평범한 AspectJ로 테스트했습니다.

  2. ==============================

    2.이것은 해결책은 아니지만 한 걸음 더 나아가 야합니다.

    이것은 해결책은 아니지만 한 걸음 더 나아가 야합니다.

    나는 당신이 당신의 주석에 오타를 만든다고 가정하고있다. 아마 당신은 @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){}
    
  3. from https://stackoverflow.com/questions/16617374/how-do-i-pass-arguments-to-spring-aop-advice-with-annotated-parameters by cc-by-sa and MIT license