在我的项目中,我正在尝试迁移
的所有用法Foo foo = (Foo) beanFactory.getBean("name");
进入
Foo foo = beanFactory.getBean(Foo.class);
好处是显而易见的:类型安全,代码复杂度较低,常量较少等等。通常,这些行位于静态遗留环境中,这种布线是唯一的选择。
这一切都很好,直到有一天用户开始抱怨来自Spring internals的缓慢。所以我启动了一个分析器来查找
中的热点 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显着改善了情况,但仍然比String查找慢 ~25 倍!事实证明,这种尝试只解决了一半的问题:它缓存了bean的名称以保存在O(n)迭代上,但仍然需要调用isAssignableFrom
来验证类型。
描述的问题不仅与我的场景有关,而且也适用于使用@Autowired
的bean,并且在循环内创建bean的情况下可能会感觉很难。
其中一个解决方案是覆盖其中一个bean工厂方法并缓存is-this-bean-of-same-type检查结果,但显然这应该在Spring中完成,而不是在我自己的代码中完成。 / p>
是否还有其他人遇到类似问题并找到解决方法?
答案 0 :(得分:5)
此问题现在在Spring中以SPR-6870的分辨率得到解决。有关详细信息,请参阅其中的分辨率该修复程序从版本3.2.0.RELEASE和3.1.2。
开始提供答案 1 :(得分:2)
大多数Spring应用程序在启动时将事物连接在一起,而不是在运行时从上下文中获取bean。即便如此,除非您在应用程序的常规运行期间大量更改应用程序上下文,否则您不应该多次获取bean。
鉴于此,如果您的用户抱怨速度缓慢,那么您的真正问题似乎是查找过多的bean;你使用较慢的方法就可以解决真正的问题。
我会尝试迁移到Java Config(在Java中配置您的依赖项,我相信在Spring 3.0中支持)并配置您的应用程序以在启动时连接所有bean。这也有一个好处,即如果无法满足依赖性,您的应用就无法启动。