【问题标题】:Spring wiring by type is slower by magnitude than wiring by name按类型接线的弹簧比按名称接线慢
【发布时间】:2012-03-14 20:03:49
【问题描述】:

在我的项目中,我正在尝试迁移

Foo foo = (Foo) beanFactory.getBean("name");

进入

Foo foo = beanFactory.getBean(Foo.class);

好处是显而易见的:类型安全、更少复杂的代码、更少无用的常量等。通常,此类行位于静态遗留上下文中,这种布线是唯一的选择。

这一切都很好,直到有一天用户开始抱怨原来来自 Spring 内部的缓慢。所以我启动了一个分析器来在

中找到一个热点

org.springframework.beans.factory.support.AbstractBeanFactory::doGetBean(String, Class<T>, Object[], boolean)

调用昂贵的

Class.isAssignableFrom(anotherClass).

我快速创建了一个小型性能测试,以找出字符串名称和类型查找之间的速度差异是 350 倍(我使用 StaticApplicationContext 进行此测试 FAIW)!

在调查此问题时,我发现 SPR-6870 的投票数很高,但由于某种原因没有得到解决。这让我找到了an attempt to solve this problem,它确实显着改善了这种情况,但仍然比通过字符串查找慢 ~25 倍!事实证明,这种尝试只解决了一半的问题:它缓存了 bean 的名称以保存 O(n) 迭代,但仍然需要调用 isAssignableFrom 来验证类型。

所描述的问题不仅与我的场景有关,而且还与使用 @Autowired 的 bean 相关,并且在循环内创建 bean 的情况下会感到困难。

解决方案之一是覆盖其中一个 bean 工厂方法并缓存 is-this-bean-of-the-same-type 检查结果,但显然这应该在 Spring 中完成,而不是在我自己的代码中。

是否有其他人遇到类似问题并找到了解决方案?

【问题讨论】:

  • 那么,你想按类型自动装配,但不做任何类型检查?
  • 我希望对同一类型进行第二次调用,以避免昂贵的类型检查。或者至少我希望能够指定这是启用还是禁用。对象创建是如此基本的事情,像这样的小优化可以产生很大的不同。

标签: java performance spring dependency-injection autowired


【解决方案1】:

这个问题现在在 Spring 中解决了,分辨率为SPR-6870。有关详细信息,请参阅那里的分辨率 cmets。该修复程序从 3.2.0.RELEASE 和 3.1.2 版本开始提供。

【讨论】:

  • 我们使用的是 spring 3.2.1,但应用程序在启动期间花费的大部分时间仍然是按类型自动装配。有什么建议吗?
【解决方案2】:

大多数 Spring 应用程序在启动时将事物连接在一起,而不是在运行时从上下文中获取 bean。尽管如此,除非您在应用程序的常规运行期间大量更改应用程序上下文,否则您不应多次获取 bean。

鉴于,如果您的用户抱怨速度慢,那么您的真正问题似乎是 bean 查找过多;您使用较慢的方式这样做才暴露了真正的问题。

我会尝试迁移到 Java Config(在 Java 中配置您的依赖项,我相信在 Spring 3.0 中支持)并配置您的应用程序以在启动时连接所有 bean。这还有一个好处是,如果无法满足依赖关系,您的应用将无法启动。

【讨论】:

  • 我认为您真正想说的是“我的问题是我为此使用 Spring”:) 关于 Java Config - 是的,这是一个转义选项,但我仍然认为原始问题应该解决,因为它似乎会影响(从赞成票数来看)许多其他 Spring 用户。
  • 我在使用 Spring 时从未遇到过这个问题,并在一些相当大的项目中使用过它。应用程序启动时间很慢,但是一旦连接好,它就可以正常工作。我们通常按名称自动装配,但也有一些 XML 配置。我们从未直接调用 getBean。
  • “大型项目”可以有不同的场景。你关于你从未遇到过这个问题的论点是没有实际意义的。此外,我怀疑使用 Java Config(例如,而不是 XML)的建议是否会有所帮助——如果使用相同类型的 BeanFactory,它将遇到同样的问题。损坏的是工厂 bean 实例化实现,而不是程序集。
  • 我的意思是,您在启动时预先支付实例化的代价,而不是每次用户使用您的应用程序时。这可能是您的应用程序中的基本设计更改,但在应用程序的正常运行时操作期间查询 bean 的上下文并不习惯。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-05
  • 2013-02-28
  • 2015-02-15
  • 2015-09-17
  • 2012-05-06
相关资源
最近更新 更多