Spring AOP启动时间慢

发布于 2024-10-11 17:14:42 字数 517 浏览 2 评论 0原文

我们使用带有 @AspectJ 样式注释和 > 的 Spring (3.0.5) AOP。。我们将它用于事务、审计、分析等。它运行良好,只是随着添加更多代码,应用程序的启动时间不断增长。

我做了一些分析,发现大部分时间都花在 Spring 容器初始化期间,更具体地说,org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory) - 大约需要 35秒。 org.springframework.aop.support.AopUtils.canApply(Pointcut, Class, boolean) - 大约需要 15 秒。

我的目标是应用程序在 5-10 秒内启动,而不是像现在那样大约 45 秒,因此任何提示将不胜感激。

We're using Spring (3.0.5) AOP with @AspectJ style annotations and <aop:aspectj-autoproxy/>
. We use it for transactions, auditing, profiling etc. It works fine except that the startup time of the application is continuously growing as more code is being added.

I have done some profiling and found that most of the time is spent during Spring container initialization, more specifically org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(String, ObjectFactory) - takes about 35 sec.
org.springframework.aop.support.AopUtils.canApply(Pointcut, Class, boolean) - takes about 15 sec.

My goal is for the application to start in 5-10 seconds and not ~45 sec as it does now, so any tips would be much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

遮了一弯 2024-10-18 17:14:42

我遇到了同样的问题,事实证明 Spring AOP 自动代理在启动时花费了大量时间使用 bcel 加载类(没有缓存,因此在尝试计算时一次又一次加载相同的类,如 java.lang.Object...)找出哪些建议适用。
通过编写更细粒度的点切割(例如使用内部,@within)可以在一定程度上改进它,但我找到了一个如果所有切入点都使用@annotation编写的解决方案,效果会更好。

1) 使用以下命令停用自动代理: spring.aop.auto=false

2) 编写 AnnotationAwareAspectJAutoProxyCreator 的自定义子类,以根据您自己的标准过滤要装饰的 bean,例如,这是基于包和注释的:

@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,   TargetSource targetSource) {
  if (beanClass != null && isInPackages(beansPackages, beanClass.getName()) &&   hasAspectAnnotation(beanClass)) {
    return super.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
  } else {
    return DO_NOT_PROXY;
  }
}

在我的例子中时间从60秒缩短至15秒。

我希望它能帮助某人和北极熊

I had the same issue, it turns out Spring AOP auto-proxying spends a LOT of time at startup loading classes with bcel (without caching, so loading again and again same classes like java.lang.Object...) when trying to figure out which advices apply.
It can be somewhat improved by writing more fine-grained Point cuts (use within, @within for example) but I've found a solution that worked better if all your pointcuts are written with @annotation.

1) Desactivate auto-proxy with: spring.aop.auto=false

2) Write a custom subclass of AnnotationAwareAspectJAutoProxyCreator to filter beans to be decorated according to your own criteria, for example this one is based on package and annotations :

@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,   TargetSource targetSource) {
  if (beanClass != null && isInPackages(beansPackages, beanClass.getName()) &&   hasAspectAnnotation(beanClass)) {
    return super.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
  } else {
    return DO_NOT_PROXY;
  }
}

In my case startup time down from 60s to 15s.

I hope it will help someone and polar bears

ζ澈沫 2024-10-18 17:14:42

从您发布的内容来看,您使用的加载时间编织似乎会导致启动损失,因为系统必须在加载时编织所有类。如果您主要关心的是启动时间,那么我建议您切换到编译时编织。您可以在 spring 文档(第 6 章第 8 节)或 AspectJ 站点 (http://www.eclipse.org/aspectj/docs.php) 中找到有关如何执行此操作的说明

。 AspectJ 编译器相对直接:

  1. 删除
    表示法
    从您的上下文文件中。
  2. 添加一个
    构建的aspectJ编译步骤
    文件。在 AspectJ 网站上,您应该
    能够找到一个ant插件,
    codehaus 有一个 Maven 插件。这里
    是我们双方如何相处的例子。

对于 Maven:

<plugin>
     <groupId>org.codehaus.mojo</groupId>
     <artifactId>aspectj-maven-plugin</artifactId>
     <version>1.3</version>
     <configuration>
     <verbose>true</verbose>
      <source>1.6</source>
      <target>1.6</target>
      <complianceLevel>1.6</complianceLevel>
      <showWeaveInfo>true</showWeaveInfo>
      <aspectLibraries>
        <aspectLibrary>
                                <groupId>org.springframework</groupId>
                                <artifactId>spring-aspects</artifactId>
                            </aspectLibrary>
                        </aspectLibraries>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>compile</goal>   
                            </goals>
                        </execution>
                    </executions>
                </plugin>

对于 Ant

 <taskdef
            resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
            <classpath>
                <pathelement location="${lib.dir}/AspectJ_1.6.8/aspectjtools.jar"/>
            </classpath>
        </taskdef>

  <iajc aspectPath="${file.reference.spring-aspects.jar}; ${build.classes.dir}/path/to/custom/aspects"
              classpath="${lib.dir}/AspectJ_1.6.8/aspectjrt.jar; ${javac.classpath}"
              inpath="${build.classes.dir}"
              destDir="${build.classes.dir}"
              showWeaveInfo="true" />

From what you've posted it looks like your using Load Time Weaving which incurs a startup penalty because the system has to weave all the classes as they are being loaded. If your primary concern is startup time, then I would suggest you switch to Compile Time Weaving. You can find instructions on how to do this in the spring documentation (Chapter 6, Section 8) or in at the AspectJ site (http://www.eclipse.org/aspectj/docs.php)

Switching to Compile time weaving with the AspectJ compiler is relatively stragiht forward:

  1. Remove the
    <aop:aspectj-autoproxy/> notation
    from your context file.
  2. Add a
    aspectJ compile step to your build
    file. On the AspectJ site you should
    be able to find an ant plugin,
    codehaus has a maven plugin. Here
    are examples of how to us both.

For Maven:

<plugin>
     <groupId>org.codehaus.mojo</groupId>
     <artifactId>aspectj-maven-plugin</artifactId>
     <version>1.3</version>
     <configuration>
     <verbose>true</verbose>
      <source>1.6</source>
      <target>1.6</target>
      <complianceLevel>1.6</complianceLevel>
      <showWeaveInfo>true</showWeaveInfo>
      <aspectLibraries>
        <aspectLibrary>
                                <groupId>org.springframework</groupId>
                                <artifactId>spring-aspects</artifactId>
                            </aspectLibrary>
                        </aspectLibraries>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>compile</goal>   
                            </goals>
                        </execution>
                    </executions>
                </plugin>

For Ant

 <taskdef
            resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
            <classpath>
                <pathelement location="${lib.dir}/AspectJ_1.6.8/aspectjtools.jar"/>
            </classpath>
        </taskdef>

  <iajc aspectPath="${file.reference.spring-aspects.jar}; ${build.classes.dir}/path/to/custom/aspects"
              classpath="${lib.dir}/AspectJ_1.6.8/aspectjrt.jar; ${javac.classpath}"
              inpath="${build.classes.dir}"
              destDir="${build.classes.dir}"
              showWeaveInfo="true" />
猫七 2024-10-18 17:14:42

显然,如果您有很多非单例 bean,这是一个已知问题。 Spring 3.1 似乎有一个修复: https://jira.springsource.org/browse/SPR -7328

Apparently this is a known issue if you have a lot of non-singleton beans. There seems to be a fix for Spring 3.1: https://jira.springsource.org/browse/SPR-7328

北笙凉宸 2024-10-18 17:14:42

我不确定它是否适用于您的情况,但是 Spring 性能可以通过使用 CachingBeanFactory 来提高

这通常适用于连接 bean 时,但根据方面的应用和连接方式,它可能会带来改进。

I am not sure that it applies to your situtation, but Spring performance can be improved by empolying a CachingBeanFactory.

This usually applies when wiring beans, but depending on how your aspects are applied and wired, it might bring improvements.

人海汹涌 2024-10-18 17:14:42

你有循环依赖吗?这就是杀死我当前应用程序的原因。

我知道这并不是一个真正的解决方案,但我会分解上下文以在不同的虚拟机中运行不同的服务,SOA 风格。这应该允许您的所有应用程序有一个较短的启动时间,并且还应该为您提供一定的灵活性,以更轻松地更改这些服务的实现,测试少量的代码等。

我没有在我的一个应用程序中这样做现在启动时间约为 3/4 分钟,这太疯狂了(我们有几千个豆子)。这个问题不会消失,只会变得更糟,但如果你太晚才尝试解决这个问题,那么该应用程序就会太大并且很难分解。

我要研究的另一件事是休眠,创建会话工厂可能非常慢。

Do you have any circular dependency? That's what's killing my current app.

I know that's not really a solution but I would break up the context to run different services in different vms, SOA-style. That should allow all your apps to have a small startup time and that should also give you some flexibility to change the implementation of these services more easily, small amount of code to test, etc.

I didn't do that in one of my apps and now startup time is at about 3/4 mins which is crazy (we have a couple of thousand beans). That problem doesn't go away, it will only get worse, but if you try to do something about it too late, the app will be too big and too difficult to break up.

Another thing I would look into is hibernate, creating the session factory can be pretty slow.

千里故人稀 2024-10-18 17:14:42

在我将jdk1.7改回jdk1.6之前,我也遇到了同样的问题。
到了 jdk1.7,我的应用程序在“初始化 Spring root WebApplicationContext”上挂起超过 30 秒。我改回来后,10秒后就启动了。

I had the same problem, before I change jdk1.7 back to jdk1.6.
By jdk1.7, my app hang on “Initializing Spring root WebApplicationContext” for more tha 30 seconds. After I change back, it startup in 10sec.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文