继续使用AspectJ的变量参数

时间:2011-08-30 14:14:00

标签: java aspectj

我正在尝试使用AspectJ规范化应用程序中的URI。我正在使用以下代码捕获对传入java.net.URI参数的方法所做的每个调用:

Object around() : execution(* *(..,java.net.URI,..)) {
    for ( Object arg : thisJoinPoint.getArgs() ) {
        if ( arg instanceof URI ) {
            // normalize
        }
    }
    return proceed();
}

但是,由于URI是不可变的,我无法将规范化值交换到现有对象中。我需要的是调用继续使用新的,规范化的URI对象(并且可能传递其他参数不变)。但是,继续调用只允许我传递由连接点收集的参数。有没有办法为可变数量的参数完成此操作(主要是对任何URI参数感兴趣,但愿意收集并传递所有参数)?

3 个答案:

答案 0 :(得分:3)

您需要更改建议的签名:

Object around(Object[] args) : execution(* *(..,java.net.URI,..)) && args(args) {
    for(int i = 0; i < args.length; i++){
        Object arg = args[i];
        if ( arg instanceof URI ) {
            args[i] = normalizeUrI((URI)arg);
        }
    }
    return proceed(args);
}

更新:遗憾的是上面的代码不起作用。但这应该:

Object around() throws URISyntaxException : execution(* **.*(..,URI,..)) {
    final Object[] args = thisJoinPoint.getArgs();
    for(int i = 0; i < args.length; i++){
        final Object arg = args[i];
        if ( arg instanceof URI ) {
            args[i] = normalizeUrI((URI)arg);
        }
    }
    try{
        return ((ProceedingJoinPoint)thisJoinPoint).proceed(args);
    } catch(final Throwable e){
        throw new IllegalStateException(e);
    }
}

答案 1 :(得分:1)

以下内容应该是评论而非完整答案,但我的有限代表不允许我发表评论......

问题中的代码以及Sean Patrick Floyd的答案中的代码将无效,因为在方法签名模式中只能出现一次通配符“..”。可以找到here的简短解释。

答案 2 :(得分:0)

我知道这是一个老问题,但官方仍未解决​​。我刚看到它,所以我要回答它:

您提到URI是不可变的。所以基本上这是对正确解决方案的暗示:拦截对象创建(构造函数调用)并在around()建议中检查结果。如果没有问题,请传递未更改的URI,否则创建一个新的,修复或暗杀任何错误。

假设您有此应用程序类创建URI:

package de.scrum_master.aspectj.sample.uri;

import java.net.URI;
import java.net.URISyntaxException;

public class URIApp {
    public static void main(String[] args) throws URISyntaxException {
        URI[] uris = {
            new URI("https://google.com?search=olympics"),
            new URI("http://yahoo.com/mail/login"),
            new URI("https://facebook.com/user?name=kriegaex"),
            new URI("http://stackoverflow.com/questions/123456")
        };
        for (URI uri : uris)
            System.out.println(uri);
    }
}

进一步假设我们认为所有URI都具有“http”不安全的方案/协议,因此是错误的。我们想通过使用“https”将URI替换为另一个来解决此问题。我们将在以下方面做到这一点:

package de.scrum_master.aspectj.sample.uri;

import java.net.URI;
import java.net.URISyntaxException;

public aspect URIFixer {
    pointcut uriCreation() : call(URI.new(..)) && !within(URIFixer);

    URI around() throws URISyntaxException : uriCreation() {
        URI result = proceed();
        return isOk(result) ? result : fix(result);
    }

    boolean isOk(URI uri) {
        return "https".equals(uri.getScheme());
    }

    URI fix(URI uri) throws URISyntaxException {
        return new URI("https", uri.getAuthority(), uri.getPath(), uri.getQuery(), uri.getFragment());
    }
}

我希望这可以回答你的问题,即使是姗姗来迟。我想我应该在这里记录解决方案,以供其他可能找到它的用户进一步参考。