2012-10-11 10 views
11

Her biri yöntem bağımsız değişkenlerini değiştiren iki yönü var. Her iki özellik de aynı yönteme uygulandığında, zincirlenecek yönlerin uygulanmasını beklerdim ve ilk bakışta değiştirilen argümanların joinPoint.getArgs(); aracılığıyla ikinci görünüme ulaşmasını beklerdim, ancak her yönün sadece orijinal argümanlar; ikinci yön, değiştirilmiş değerleri asla görmez. Bir örnek yapmacık ettik:Parametreleri bir bakışta birden fazla yönde değiştirme Önerileri sağlama

test sınıf

:

public class AspectTest extends TestCase { 
    @Moo 
    private void foo(String boo, String foo) { 
     System.out.println(boo + foo); 
    } 

    public void testAspect() { 
     foo("You should", " never see this"); 
    } 
} 

yöntem foo() iki yönü ile tavsiye edilir:

@Aspect 
public class MooImpl { 

    @Pointcut("execution(@Moo * *(..))") 
    public void methodPointcut() {} 

    @Around("methodPointcut()") 
    public Object afterMethodInControllerClass(ProceedingJoinPoint joinPoint) throws Throwable { 
     System.out.println("MooImpl is being called"); 
     Object[] args = joinPoint.getArgs(); 
     args[0] = "don't"; 
     return joinPoint.proceed(args); 
    } 
} 

ve ...

@Aspect 
public class DoubleMooImpl { 

    @Pointcut("execution(@Moo * *(..))") 
    public void methodPointcut() {} 

    @Around("methodPointcut()") 
    public Object afterMethodInControllerClass(ProceedingJoinPoint joinPoint) throws Throwable { 
     System.out.println("DoubleMooImpl is being called"); 
     Object[] args = joinPoint.getArgs(); 
     args[1] = " run and hide"; 
     return joinPoint.proceed(args); 
    } 
} 

Çıkışın şu şekilde olmasını beklerim:

... ama geçerli:

MooImpl is being called 
DoubleMooImpl is being called 
You should run and hide 

mıyım tavsiye etrafında yoluyla argümanlar değiştirmek için doğru bir yaklaşım kullanarak?

+0

Lütfen AspectJ kullanıcılarının e-posta listesine üye olup burada sorunuz. Orada yetkili bir cevap almalısın. Ben de sonuçla ilgilenirim. – kriegaex

cevap

2

Bu, bir görünüm sırası sorunu gibi gelmiyor, yöntem argümanlarının java'da nasıl ele alındığı daha fazladır - argümanlara yapılan başvurular, ilk bağımsız değişkeniniz bir String olduğundan, String referansının neyi işaretlediğini değiştirerek Aslına bakarsanız, orijinal String'i hiçbir şekilde etkilemezsiniz ve bu şekilde geçer.

Bunun yerine, bir StringBuilder veya başka bir değiştirilebilen türde aktarmayı ve ardından durumu değiştirmeyi deneyebilirsiniz, durum değişikliği daha sonra doğru olarak yansıtılmalıdır.

Güncelleme:

Ben değişken türü ile test edilmiş ve bunun beklendiği gibi değiştirir:

@Aspect 
public class MooImpl { 

    @Pointcut("execution(@Moo * *(..))") 
    public void methodPointcut() {} 

    @Around("methodPointcut()") 
    public Object afterMethodInControllerClass(ProceedingJoinPoint joinPoint) throws Throwable { 
     System.out.println("MooImpl is being called"); 
     Object[] args = joinPoint.getArgs(); 
     ((StringBuilder)args[0]).append("****"); 
     return joinPoint.proceed(args); 
    } 
} 

ve DoubleMooImpl:

@Aspect 
public class DoubleMooImpl { 

    @Pointcut("execution(@Moo * *(..))") 
    public void methodPointcut() {} 

    @Around("methodPointcut()") 
    public Object afterMethodInControllerClass(ProceedingJoinPoint joinPoint) throws Throwable { 
     System.out.println("DoubleMooImpl is being called"); 
     Object[] args = joinPoint.getArgs(); 
     ((StringBuilder)args[1]).append("****"); 
     return joinPoint.proceed(args); 
    } 
} 

@Moo 
private void foo(StringBuilder boo, StringBuilder foo) { 
    System.out.println(boo.toString() + foo.toString()); 
} 

public void testAspect() { 
    foo(new StringBuilder("You should"), new StringBuilder(" never see this")); 
} 

MooImpl Aspect ile

ve bu çıktıyı almak: günlerdir yolda yapılmış sonra

MooImpl is being called 
DoubleMooImpl is being called 
You should**** never see this**** 
+0

Değişken tip olsun ya da olmasın, davranış aynıdır. –

+0

Sadece test ettim, cevabımı daha fazla ayrıntıyla güncelliyorum. Sizin durumunuzda [0] ya da [1] hatalarını değiştirmeden önce doğru nesneyi işaret etmeden önce, ancak "args [0] =" yapma "derken, referans marka farklı bir nesneyi işaret ediyor tamamen. Aldığınız args dizisi argüman referanslarının sadece bir kopyasıdır, bu yüzden argüman dizisini değiştirmek gerçekten herhangi bir etkiye sahip değildir, eğer değiştirirseniz, örneğimde yaptığım gibi yansıyacaktır. –

+0

Dizinin argümanların bir kopyası olduğunu anlıyorum. Anlamadığım şey, neden iki yönün ikincisinin, ilk yönün ilerlemeyi başlatmasıyla (argümanlar) geçen argümanların bir kopyasını almamasıdır. –

3

, sonunda bu düşünmeye ve soruya cevap etrafında aldık. Öznitelik AspectJ sözdizimini kullanırsam, tamamının @AspectJ notasyonu ile rahat hissetmediğimi umarım iyidir.

public class AspectTest { 
    @Moo 
    private void foo(String boo, String foo) { 
     System.out.println(boo + foo); 
    } 

    public static void main(String[] args) { 
     new AspectTest().foo("You should", " never see this"); 
    } 
} 
public aspect MooImpl { 
    pointcut methodPointcut() : execution(@Moo * *(String, ..)); 

    Object around(String firstArg) : methodPointcut() && args(firstArg, ..) { 
     System.out.println("MooImpl is being called"); 
     return proceed("don't"); 
    } 
} 
public aspect DoubleMooImpl { 
    pointcut methodPointcut() : execution(@Moo * *(*, String, ..)); 

    Object around(String secondArg) : methodPointcut() && args(*, secondArg, ..) { 
     System.out.println("DoubleMooImpl is being called"); 
     return proceed(" run and hide"); 
    } 
} 

Hatan

import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 

@Retention(RetentionPolicy.RUNTIME) 
public @interface Moo {} 
yanlış olan getArgs() yoluyla alınan argümanlar idare edebilir varsaymak oldu.Argümanları proceed()'a iletmek için, yukarıda gösterdiğim args() aracılığıyla onlara başvurmanız gerekir. Lütfen iki açıdan birinci ve ikinci String argümanını almak için sözdizimi not edin.

Bu, sorununuzu çözmelidir.

+0

@AspectJ stilini kullanarak, aynı işlevi elde etmek için 'ProceedingJointPoint.proceed (Object [] args)' işlevini kullanmanız gerekir, ancak semantikler biraz farklıdır ve [javadoc] 'a (http: // Kesin parametreler için www.eclipse.org/aspectj/doc/released/runtime-api/org/aspectj/lang/ProceedingJoinPoint.html). –