spring 上的 aop 性能(idk,aspectj)

aop performance on spring (idk, aspectj)

我尝试在 Spring 框架 4.1.6 和

上测试 AOP 的性能

AOP 方法很干净,jdk 动态代理和 aspectJ。

我向他们提出了一到五个简单的建议,并检查了每个建议的经过时间。

结果:

jdk动态代理:

aspectJ (ctw):

干净(无方面):

在测试它们之前,我预计 AspectJ (ctw) 会比 Jdk 动态代理更快,因为 AspectJ 修改了字节码。但是即使它们之间没有性能差异也是错误的。

所以,我检查了目标 class(.class) modified to recognize that AspectJ Compiler used and found bytecode modified.

这里,我有一个问题: 它们之间有什么性能差异吗? (idk动态代理,aspectj,无aop)

我的代码:

public class HelloAOP {

public static void main(String [] args) {

    ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/application-context.xml");
    Order order = (Order) ctx.getBean("orderImpl");
    SimpleDateFormat format = new SimpleDateFormat("mm:ss.SSS");

    StopWatch watch = new StopWatch();

    watch.start();
    order.placeOrder();
    watch.stop();

    System.out.println("Elapsed: " + format.format(watch.getTotalTimeMillis()));
    }
}

目标:

@Service
public class OrderImpl implements Order {
    public void placeOrder() {
        System.out.println("::Target Object");
        for(long i = 0; i < 5000000000L; i++);
    }
}

看点:

@Aspect
@Component
public class Aspect1 {

    @Before("execution(* com.cafe.beans.impl.OrderImpl.placeOrder())")
    public void aspect() {
        System.out.println("Aspect 1 *");
    }
}

pom.xml:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>4.1.6</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>4.1.6</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-instrument</artifactId>
        <version>4.1.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.6</version>
    </dependency>

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.8.6</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjtools</artifactId>
        <version>1.8.6</version>
    </dependency>

<build>
    <finalName>testAop</finalName>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>3.3</source>
                <target>3.3</target>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <includes>
                    <include>**/*Tests.java</include>
                </includes>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.7</version>
            <configuration>
                <showWeaveInfo>true</showWeaveInfo>
                <verbose>true</verbose>
                <complianceLevel>1.8</complianceLevel>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

您没有看到任何差异,您不应该感到惊讶,因为您只是在测量一个方法调用。 99.9% 的测量时间是您方法中的循环。因此,您没有衡量正确的事情。你应该反过来做,也许类似于我所做的 here:

  • 该方法应该什么都不做或几乎什么也不打印。
  • 你应该测量重复调用方面建议方法的总时间,因为你想了解应用方面的开销,而不是方法体运行时(方法体在你的方面保持不变)。

现在您可以将 Spring AOP 与 AspectJ 的性能进行比较,应该会发现 AspectJ 更胜一筹。一些注意事项:

  • 我希望您知道您需要更改 Spring 配置以便从 Spring AOP 切换到 AspectJ,反之亦然。例如。如果您一直使用 AspectJ Maven 插件进行构建,您将使用编译时 AspectJ 织入,无论您是否配置 Spring 以使用 Spring AOP 或 AspectJ 通过加载时织入(如所述)在 Spring 手册中,第 10.8 Using AspectJ with Spring applications.
  • 部分
  • 你应该测量不同类型的切入点和建议,例如@Before/@After 对比 @Around,(不)通过 this()target()args() 等使用参数绑定
  • 另请注意,您的示例代码在 class 而不是接口上使用切入点。 JDK 动态代理不能直接在 classes 上工作,但只能在接口上工作。为了在 classes 上应用 Spring AOP,您需要将 CGLIB 作为 Spring 中的依赖项,否则它根本无法工作。 编辑: 好的,您的 class 实现了 Order 接口,因此它可能仍然可以与 JDK 动态代理一起使用。