按类型划分的弹簧布线比按名称布线要慢
在我的项目中,我正在尝试迁移所有用法
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。 这也有一个好处,即如果无法满足依赖关系,您的应用就无法启动。
- Methods.class中的代码重用与策略模式和dependency injection
- @Component和@Named都是同一个bean类
- Spring IoC – dependency injection – > NullPointerException
- Struts2中的dependency injection访问会话Scoped Bean
- Java Guice – 如何将整数值绑定到我的类/对象?
- Guice在注入的构造函数参数上忽略@Nullable
- Spring ServiceLocator还是纯工厂模式?
- Jersey和spring集成 – bean Injections在运行时为null
- HK2没有用jersey注入HttpServletRequest