AspectJ - почему «совет, определенный в XYZ, не был применен»? - PullRequest
9 голосов
/ 06 июня 2011

Я только начал играть с AspectJ (1.6.11).Я отправляю электронные письма через общедоступную библиотеку электронной почты, и я хотел бы знать, сколько времени занимает отправка сообщения.Так вот мой код отправки электронной почты:

import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;

public class EmailTest
{
    public static void main(String[] args) throws EmailException
    {
        Email e = new SimpleEmail();
        e.setHostName("localhost");
        e.setFrom("foo@localhost");
        e.addTo("batto@localhost");
        e.setSubject("Test " + System.currentTimeMillis());
        e.setMsg("Message");
        e.send();
    }
}

, и это мой аспект:

public aspect EmailAspect
{
    private long start;

    pointcut conn() : call(* javax.mail.Transport.send(..));

    void around() : conn() {
        start = System.currentTimeMillis();
        Throwable t = null;
        try {
            proceed();
        }
        catch(Throwable _t) {
            t = _t;
        }
        long spent = System.currentTimeMillis() - start;
        System.out.println("Send time: " + spent);
        if (t != null) {
            throw new RuntimeException(t);
        }
    }
}

Однако, когда я скомпилирую его с:

java -jar ../lib/aspectjtools-1.6.11.jar -cp "$CLASSPATH" -source 6 Email*{java,aj}

я получаюследующее предупреждение:

/home/batto/work/ajtest/test/EmailAspect.aj:8 [warning] advice defined in EmailAspect has not been applied [Xlint:adviceDidNotMatch]


1 warning

И, конечно, аспект не работает.Я пробовал советы до () / после (), разные шаблоны в call (), но все это заканчивалось одним и тем же предупреждением.

Я отладил программу в Eclipse (с источниками обыкновенных писем), и я знаю,что Transport.send () выполняется.

В чем проблема?

Спасибо.

ОБНОВЛЕНИЕ

Итак, яЯ только что выяснил, что мне нужен исходный код javax.mail.Transport для метода ткачества, который я использовал (ткачество источника).Поэтому я использовал бинарное плетение, и это сработало.Однако я передумал, и теперь я хочу измерить время java.net.Socket.connect (..) (org.apache.commons.mail.Email.send (..) вызывает javax.mail.Transport.send (..) который вызывает java.net.Socket.connect (..), я проверил это отладкой в ​​Eclipse).Но я не хочу включать весь JDK в мой скомпилированный код.Поэтому я попробовал ткачество во время загрузки.Это мой модифицированный аспект:

public aspect EmailAspect {
    // Some day I'll learn what's the difference between call() and execution()
    pointcut conn() :
        call(* java.net.Socket.connect(..)) ||
        execution(* java.net.Socket.connect(..));

    before() : conn() {
        System.out.println("It works");
    }
}

И эти шаги, которые я сделал для компиляции и запуска программы:

$ mkdir META-INF
$ cat >META-INF/aop.xml
<aspectj>
  <aspects>
    <aspect name="EmailAspect"/>
    <!-- I think this is not neccessary -->
    <include within="java..*"/>
    <include within="javax..*"/>
  </aspects>
  <weaver>
    <include within="java..*"/>
    <include within="javax..*"/>
  </weaver>
</aspectj>
$ # add jars from ../lib to CLASSPATH
$ javac -source 6 EmailTest.java
$ java -jar ../lib/aspectjtools-1.6.11.jar -cp ".:$CLASSPATH" -source 6 EmailAspect.aj
$ java -cp ".:$CLASSPATH" -javaagent:../lib/aspectjweaver-1.6.11.jar EmailTest

Но это не работает: (.

Ответы [ 2 ]

2 голосов
/ 07 июня 2011

Итак, я только что решил проблему с переплетением времени загрузки.Я изменил aop.xml на:

<aspectj>
  <aspects>
    <aspect name="EmailAspect"/>
  </aspects>
  <weaver options="-verbose -Xset:weaveJavaxPackages=true -Xset:weaveJavaPackages=true">
  </weaver>
</aspectj>

Я нашел ответ здесь https://bugs.eclipse.org/bugs/show_bug.cgi?id=149261#c11 (а также среда выполнения AspectJ сообщала, что мне нужно предоставить опцию -Xset: weaveJavaxPackages = true, ябыло слишком глупо: ().

0 голосов
/ 07 июня 2011

Быстрая проверка документации apache, похоже, показывает, что ни Email, ни SimpleEmail не являются экземплярами Transport.Поэтому вы можете изменить pointcut на:

pointcut conn (): call (* SimpleEmail.send (..));

...