当前位置: 首页 > 知识库问答 >
问题:

AspectJ aspect不适用于LTW场景

安毅
2023-03-14

我试图在独立应用程序中使用AspectJ,但似乎不起作用。

以下是我创建的类-

package oata.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectJTest {


    @Around("execution(* *..*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("around fired");
        jp.proceed();
    }
}
package oata;

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

@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface AspectTest {
}
package oata;

import oata.AspectTest;

public class TestAspect {
    public void doItWithout(int i) {
        double s = Math.acos(i);
    }

    @AspectTest
    public void doItAnnotated(int i) {
        double s = Math.acos(i);
    }

    public void doItAspect(int i) {
        double s = Math.acos(i);

    }
}
package oata;

import java.util.Date;

public class Test {
    public Test() {
    }

    public static void main(String arg[]) {
        // performance testing
        // invoke method without aspect
        long t1 = new Date().getTime();
        for (int i = 0; i < 1; i++) {
            new TestAspect().doItWithout(i);
        }
        System.out.println("Invoke without aspect:"
                + (new Date().getTime() - t1));
        // invoke method with annotated aspect
        t1 = new Date().getTime();
        for (int i = 0; i < 1; i++) {
            new TestAspect().doItAnnotated(i);
        }
        System.out.println("Invoke annotated aspect method:"
                + (new Date().getTime() - t1));
        // invoke method with aspect but not annotated
        t1 = new Date().getTime();
        for (int i = 0; i < 1; i++) {
            new TestAspect().doItAspect(i);
        }
        System.out.println("Invoke aspect method:"
                + (new Date().getTime() - t1));
    }
}

同样在src/META\u-INF文件夹下,我创建了aop。xml文件

<aspectj>
    <aspects>
        <aspect name="oata.aspect.AspectJTest" />
    </aspects>
    <weaver>
        <include within="oata.*" />
    </weaver>
</aspectj>

然后在我尝试运行测试时从命令行执行。java使用下面的命令实现系统。出来通知中的println无法打印-

\TestAspectJ\bin>java -javaagent:D:\Project\workspaces\RCS_3.2.1\TestAspectJ\src\aspectjweaver-1.6.10.jar oata.Test

有人能告诉我我做错了什么吗?

谢谢AA

共有2个答案

程俊健
2023-03-14

安迪说的一切都对。因为您似乎是AspectJ和Java的初学者,我对您的示例代码进行了一些重构,以帮助您入门。一路上我注意到的事情:

  • 您使用的是非常旧的AspectJ版本1.6.10。它是从2010年开始的,甚至不是最新的1.6版本(即1.6.12)。使用当前的AspectJ版本1.8.6怎么样

重构代码:

package oata;

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

@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {}
package oata;

import oata.MyAnnotation;

public class Helper {
    public double doItWithout(int i) {
        return Math.acos(i);
    }

    @MyAnnotation
    public double doItAnnotated(int i) {
        return Math.acos(i);
    }

    public double doItAspect(int i) {
        return Math.acos(i);
    }
}
package oata;

public class Application {
    private static final int LOOP_COUNT = 100000000;

    public static void main(String arg[]) {
        Helper helper = new Helper();
        System.out.printf(
            "Profiling statistics for %,d repetitions%n%n",
            LOOP_COUNT
        );

        long startTime = System.nanoTime();
        for (int i = 0; i < LOOP_COUNT; i++)
            helper.doItWithout(i);
        System.out.printf(
            "Method not targeted by aspect:%n    %,15d ns%n",
            System.nanoTime() - startTime
        );

        startTime = System.nanoTime();
        for (int i = 0; i < LOOP_COUNT; i++)
            helper.doItAnnotated(i);
        System.out.printf(
            "Method targeted by aspect because it is annotated:%n    %,15d ns%n",
            System.nanoTime() - startTime
        );

        startTime = System.nanoTime();
        for (int i = 0; i < LOOP_COUNT; i++)
            helper.doItAspect(i);
        System.out.printf(
            "Method targeted by aspect because of its name:%n    %,15d ns%n",
            System.nanoTime() - startTime
        );
    }
}
package oata.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MethodInterceptor {
    @Around("execution(@oata.MyAnnotation * *(..)) || execution(* *Aspect*(..))")
    public Object around(ProceedingJoinPoint jp) throws Throwable {
//      System.out.println("BEFORE " + jp);
        Object result = jp.proceed();
//      System.out.println("AFTER  " + jp);
        return result;
    }
}

启用aspect log语句的1个重复控制台日志示例:

Profiling statistics for 1 repetitions

Method not targeted by aspect:
            153.893 ns
BEFORE execution(double oata.Helper.doItAnnotated(int))
AFTER  execution(double oata.Helper.doItAnnotated(int))
Method targeted by aspect because it is annotated:
          3.102.128 ns
BEFORE execution(double oata.Helper.doItAspect(int))
AFTER  execution(double oata.Helper.doItAspect(int))
Method targeted by aspect because of its name:
             55.295 ns

正如您在这里看到的,每个方法只调用一次,结果并不是非常确定。

禁用方面日志语句的100000000(一亿)次重复的控制台日志示例:

Profiling statistics for 100.000.000 repetitions

Method not targeted by aspect:
        843.407.034 ns
Method targeted by aspect because it is annotated:
      1.219.571.173 ns
Method targeted by aspect because of its name:
      1.175.436.574 ns

现在的结果更具结论性:任何方面都没有针对的方法的执行速度比后两种方法快,后两种方法的执行时间约为1.2秒,这是意料之中的,因为使用的切入点可以在编译时间(对于CTW)或编织时间(对于LTW)期间静态确定。

满俊楠
2023-03-14

几件事:

  • 您的META-INF/*文件夹是否确实被复制到您运行应用程序的bin文件夹中?
  • 您正在指定oata.*的包含,这将仅包含oata包中的直接类,如果您想要更多的子包(我认为您确实需要),您需要oata...*
  • 您是否尝试过指定weaver选项="-mar ose"-这会显示任何内容?如果它没有显示任何内容,则找不到aop.xml文件。如果它确实向您显示了一些内容,它会告诉您正在打开哪些方面。也许然后使用-debug来增强它以了解更多关于正在发生的事情。
  • 我可能会包含一个!在(AeyJTest)中投诉您的切入点,或者您可能最终会自我建议并在它开始工作时因堆栈溢出而失败。
  • 最后,我知道您现在没有使用它,但如果您打算使用该注释与AeyJ匹配,则需要将其从SOURCE保留更改,因为AeyJ在字节码级别工作,并且不会查看它是否具有源代码保留。
 类似资料:
  • 我需要对表的总数进行断言,当我在映像表中为总数编写XPath时,这样做对所有场景都不起作用。我知道原因,因为表是动态的,所以有时它只有1个图像,有时它有5个图像,所以我很难编写适用于所有场景的x路径。 对于我所写的附加图像:在这里输入图像描述WebElement totalElement=driver。findElement(By.xpath(“/*[@id=“image_table”]/tbod

  • MySQL 是目前世界上最流行的开源关系数据库,大多应用于互联网行业。比如,在国内,大家所熟知的百度、腾讯、淘宝、京东、网易、新浪等,国外的 Google、Facebook、Twitter、GitHub 等都在使用 MySQL。社交、电商、游戏的核心存储往往也是 MySQL。 任何产品都不可能是万能的,也不可能适用于所有的应用场景。那么 MySQL 到底适用于哪些场景又不适用于哪些场景呢? 1.

  • 本文档所描述的 API 接口,仅限用于数据的查询,适用于 百度移动统计 站点的用户使用,适用场景有如下: 获取 百度移动统计 站点的报告数据,用于邮件发送 获取 百度移动统计 站点的报告数据,用于二次开发 查询 百度移动统计 站点中用户或应用相关的配置信息 其余需要基于百度移动统计的报表数据的业务场景

  • MIP 适用于所有需要加速的站点。 如果您的站点响应速度慢,如果您的 CDN 速度慢,如果您希望广告有更高的 ROI,那 MIP 就非常适合您的站点。 MIP 最核心,也是我们一直尽力遵守的原则是:速度最快和体验最好。 截至到目前,有超过 1w 个站点接入 MIP,他们使用 MIP 获得了极致的用户体验并且带来了客观的广告收入。 谁最应该关注 MIP 呢? 资讯阅读类的站点 电商网站 广告主 其他

  • 问题内容: 嗨,我只是简单地尝试在www.example.com上获取h1标签,该标签显示为“ Example Domain”。该代码适用于http://www.example.com,但不适用于https://www.exmaple.com。我该如何解决这个问题?谢谢 问题答案: PhantomJSDriver不支持(所有)DesiredCapabilities。 你会需要: 记录在这里:htt

  • 所以我使用这种方法写入文件,它在windows上运行完全正常,但在mac上运行时,它会创建文件,但它们是空的。 我知道数据是正确的,因为它打印正确。感谢您的任何帮助,这真的让我绊倒了。