6

我们使用带有@AspectJ样式注释的 Spring (3.0.5) AOP 和<aop:aspectj-autoproxy/> . 我们将它用于事务、审计、分析等。它工作正常,只是应用程序的启动时间随着更多代码的添加而不断增长。

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

我的目标是让应用程序在 5-10 秒内启动,而不是像现在这样约 45 秒,所以任何提示都将不胜感激。

4

6 回答 6

5

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

使用 AspectJ 编译器切换到 Compile time weaving 是相对直接的:

  1. <aop:aspectj-autoproxy/>从上下文文件中 删除 符号。
  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>

对于蚂蚁

 <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" />
于 2011-01-19T17:01:30.737 回答
5

我遇到了同样的问题,事实证明 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 秒。

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

于 2017-10-02T21:47:07.383 回答
3

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

于 2011-01-14T12:26:24.883 回答
1

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

这通常在连接 bean 时适用,但取决于您的方面如何应用和连接,它可能会带来改进。

于 2011-01-14T12:25:18.753 回答
1

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

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

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

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

于 2011-01-18T03:00:13.677 回答
0

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

于 2012-12-19T08:49:50.140 回答