【问题标题】:AspectJ - why "advice defined in XYZ has not been applied"?AspectJ - 为什么“未应用 XYZ 中定义的建议”?
【发布时间】:2011-06-06 14:58:41
【问题描述】:

我刚开始玩 AspectJ (1.6.11)。我正在通过 commons-email 库发送电子邮件,我想知道发送消息需要多长时间。这是我的电子邮件发送代码:

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

当然方面也不起作用。我尝试了 before()/after() 建议,call() 中的不同模式,但都以同样的警告告终。

我在 Eclipse 中调试了程序(使用 commons-email 源),我知道 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

但它不起作用:(。

【问题讨论】:

  • 我的 JDK 是 OpenJDK 6b18-1.8.7-5(debian 包)

标签: java aop aspectj


【解决方案1】:

所以我刚刚解决了加载时编织的问题。我将 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 选项,我太笨了:()。

【讨论】:

    【解决方案2】:

    对 apache 文档的快速检查似乎表明 Email 和 SimpleEmail 都不是 Transport 的实例。将pointcut 更改为:

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

    【讨论】:

    • 是的,但是 Email.send() 调用 Transport.send(..)。无论如何,我用二进制编织让它工作(我更新了问题)。现在问题更改为加载时编织不工作。
    • 我还添加了具有相同模式的执行()“谓词”到切入点(我不知道有什么区别,但现在没关系)。
    • @batto 没有办法通过编译时编织 (CTW) 来实现这一点?
    猜你喜欢
    • 2014-12-10
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-01
    相关资源
    最近更新 更多