按类型划分的弹簧布线比按名称布线要慢

在我的项目中,我正在尝试迁移所有用法

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

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

好处是显而易见的:类型安全性,较少复杂的代码,较少的无用常量等。通常,这些线路位于静态遗留环境中,其中这种布线是唯一的选择。

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

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

这是一个昂贵的电话

Class.isAssignableFrom(anotherClass)

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

在调查这一点时,我发现SPR-6870的票数很高,但由于某种原因没有得到解决。 这导致我尝试解决这个问题 , 这个问题确实显着改善了这种情况,但仍然比使用String查找要快25倍! 事实certificate,这种尝试只解决了一半的问题:它缓存bean的名称以保存在O(n)迭代上,但仍然必须调用isAssignableFrom来validation类型。

所描述的问题不仅与我的场景有关,而且也适用于使用@Autowired bean,并且在循环内创建bean的情况下可能会感觉很难。

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

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

现在用Spring -SPR70的分辨率解决了这个问题。 有关详细信息,请参阅其中的分辨率 从版本3.2.0.RELEASE和3.1.2开始提供此修复程序。

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

鉴于此,如果您的用户抱怨速度缓慢,那么您的真正问题似乎是查找过多的bean; 你使用较慢的方法只是表明了真正的问题。

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