Продолжить с переменными аргументами с AspectJ - PullRequest
9 голосов
/ 30 августа 2011

Я пытаюсь нормализовать URI в приложении, используя AspectJ. Я перехватываю каждый вызов метода, передавая параметр 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 ]

3 голосов
/ 30 августа 2011

Вам необходимо изменить подпись вашего совета:

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 голос
/ 03 мая 2013

Следующим должен быть комментарий, а не полный ответ, но мой ограниченный представитель не позволяет мне комментировать ...

Код в вопросе, а также в ответе Шона Патрика Флойда не будет работать, поскольку в шаблоне сигнатуры метода может быть только одно вхождение подстановочного знака "..". Краткое объяснение, почему это так, можно найти здесь .

0 голосов
/ 10 августа 2012

Я знаю, что это старый вопрос, но официально до сих пор не решен. Я только что видел это, поэтому я собираюсь ответить на него:

Вы упомянули, что 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» небезопасными и, следовательно, ошибочными. Мы хотим исправить это, заменив URI другим, используя «https». Мы сделаем это в аспекте:

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

Надеюсь, это ответит на ваш вопрос, хотя и с запозданием. Я подумал, что должен документировать решение здесь для дальнейшего использования другими пользователями, которые могут его найти.

...