spring 上的 aop 性能(idk,aspectj) [英] aop performance on spring (idk, aspectj)

查看:47
本文介绍了spring 上的 aop 性能(idk,aspectj)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试在 Spring 框架 4.1.6 上测试 AOP 的性能

I tried to test the performance of AOP on Spring framework 4.1.6 and

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

AOP methods were clean, jdk dynamic proxy and aspectJ.

我向他们提出了 1 到 5 个简单的建议,并检查了每个建议所用的时间.

I made one to five simple advices to them and checked elapsed time for each.

结果:

jdk 动态代理:

    • aspect1:2.499 秒
    • 方面 2:2.574
    • 方面 3:2.466
    • 方面 4:2.436
    • 方面 5:2.563

    aspectJ (ctw):

      • 方面 1:2.648
      • 方面2:2.562
      • 方面 3:2.635
      • 方面 4:2.520
      • 方面 5:2.574

      干净(没有方面):

        • 方面 1:2.699
        • 方面2:2.513
        • 方面 3:2.527
        • 方面 4:2.458
        • 方面 5:2.402

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

        Before testing them, I expected AspectJ (ctw) will be faster than Jdk dynamic proxy because AspectJ modified bytecode. But it was wrong even there was no performance difference among them.

        因此,我检查了修改后的目标类(.class)以识别使用了 AspectJ Compiler 并发现字节码被修改.

        So, I checked the target class(.class) modified to recognise that AspectJ Compiler used and found bytecode modified.

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

        Here, I have question: Is there any performance difference among them? (idk dynamic proxy, aspectj, no 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% 的测量时间是方法内部的循环.因此,您没有测量正确的东西.你应该反过来做,可能类似于我在这里所做的:

        You should not be surprised not to see any difference because you are just measuring one single method call. 99.9% of the time measured is the loop inside your method. Ergo you are not measuring the right thing. You should do it the other way around, maybe similar to what I did here:

        • 该方法不应执行任何操作或几乎不执行任何操作并且不打印任何内容.
        • 您应该测量重复调用方面建议的方法的总时间,因为您想了解应用方面的开销,而不是方法体运行时(方法体保持不变,您的方面).

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

        Now you can compare Spring AOP to AspectJ performance and should see that AspectJ is superior. A few caveats:

        • 我希望您知道您需要更改 Spring 配置,以便从 Spring AOP 切换到 AspectJ,反之亦然.例如.如果您一直使用 AspectJ Maven 插件进行构建,那么您将使用编译时 AspectJ 编织,无论您是将 Spring 配置为通过加载时编织使用 Spring AOP 还是 AspectJ,如 Spring 手册第 10.8 使用 AspectJSpring 应用程序.
        • 您应该衡量不同类型的切入点和建议,例如@Before/@After vs. @Around,(不)通过this()使用参数绑定,target()args()
        • 另请注意,您的示例代码在类而不是接口上使用切入点.JDK 动态代理不能直接在类上工作,但只能在接口上工作.为了在类上应用 Spring AOP,你需要 CGLIB 作为 Spring 的依赖,否则它根本无法工作.好的,您的类实现了 Order 接口,因此它可能仍然适用于 JDK 动态代理.
        • I hope you know that you need to change the Spring configuration so as to switch from Spring AOP to AspectJ and vice versa. E.g. if you use the AspectJ Maven Plugin all the time for your builds, you will use compile-time AspectJ weaving, no matter if you configure Spring to use Spring AOP or AspectJ via load-time weaving as described in the Spring manual, section 10.8 Using AspectJ with Spring applications.
        • You should measure different types of pointcuts and advice, e.g. @Before/@After vs. @Around, (not) using parameter binding via this(), target() or args() etc.
        • Please also note that your sample code uses a pointcut on a class rather than an interface. JDK dynamic proxies do not work directly on classes, though, only on interfaces. In order to apply Spring AOP on classes, you need CGLIB as a dependency in Spring, otherwise it simply will not work. Okay, your class implements the Order interface, so it might still work with JDK dynamic proxies.

        这篇关于spring 上的 aop 性能(idk,aspectj)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

        查看全文
        登录 关闭
        扫码关注1秒登录
        发送“验证码”获取 | 15天全站免登陆