首页 > 解决方案 > Spring @Autowire 与 getBean(className) 的性能

问题描述

代码有两种变体:

public class MyClass {
 public void myMethod() {
  AnotherClass object = SpringContexHolder.getContext().getBean(AnotherClass.class);
  object.doSomething();
 }
}

@Component
public class MyClass {
@Autowired
AnotherClass object;     

public void myMethod() {
 object.doSomething();
}
}

第一个变体是否会有任何性能损失(顺便说一下,它不是spring bean,只是简单的类)?自动装配是否与 getBean 一样?

PS我想我应该稍微扩展一下我的问题。情况是我加入的团队只通过getBean(className)在项目中使用Spring注入。我猜的原因是大多数已经编写的项目类都不是 Spring bean,并且在一个类中使用自动装配意味着通常也会制作依赖类 bean,依此类推,直到大多数类变成 bean...

好的,我想我理解这种方法的可测试性惩罚和整体缺乏代码风格。但是难道没有性能惩罚吗?在启动时构建的即用型 Spring 单例的性能是否存在差异,它的所有字段都是自动装配的,并且从非 Spring 非- 单人班(特别是在关键地方)?

PSS 我创建了类似 mini-benchmark 的东西(我知道由于 GC、JIT 等的工作,很难获得真实的信息,但尽管如此......)。我的结果是(数字越大越差):自动装配时间 - 193,GetBean 时间 - 2161,同一类中的方法 - 173,另一个类中的静态方法 - 206

标签: javaspringperformanceautowired

解决方案


每次需要访问时在 Spring 上下文(通常是复合的)中查找 bean 的效率会很低。您实际上是在多个哈希表中多次查找一个项目,破坏 CPU 缓存,浪费时间并可能由于更复杂的执行路径而阻止其他优化,例如内联。

绝对使用自动装配(基于注释或基于构造函数)。这样,在应用程序启动时进行一次查找,然后通过直接引用访问该类。

@Autowired即使有注释,可测试性也很好。您只需自动装配模拟而不是实际对象。还要查看MockitoSpring-Test注释以注入模拟并以其他方式增强 Spring 上下文以进行测试。


推荐阅读